<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://smwiki.info/index.php?action=history&amp;feed=atom&amp;title=%EC%9B%B9%3AMagic_Grid</id>
	<title>웹:Magic Grid - 편집 역사</title>
	<link rel="self" type="application/atom+xml" href="https://smwiki.info/index.php?action=history&amp;feed=atom&amp;title=%EC%9B%B9%3AMagic_Grid"/>
	<link rel="alternate" type="text/html" href="https://smwiki.info/index.php?title=%EC%9B%B9:Magic_Grid&amp;action=history"/>
	<updated>2026-05-12T02:31:43Z</updated>
	<subtitle>이 문서의 편집 역사</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://smwiki.info/index.php?title=%EC%9B%B9:Magic_Grid&amp;diff=3560&amp;oldid=prev</id>
		<title>Sam: 새 문서: == 개요 == Masonry와 비슷한 레이아웃을 보여주는 독구.(핀터레스트의 이미지 배치와 유사하다.)  Masonry에 비해 사용이 쉽다. &lt;br /&gt;  == 사용법...</title>
		<link rel="alternate" type="text/html" href="https://smwiki.info/index.php?title=%EC%9B%B9:Magic_Grid&amp;diff=3560&amp;oldid=prev"/>
		<updated>2021-03-24T11:29:58Z</updated>

		<summary type="html">&lt;p&gt;새 문서: == 개요 == Masonry와 비슷한 레이아웃을 보여주는 독구.(핀터레스트의 이미지 배치와 유사하다.)  Masonry에 비해 사용이 쉽다. &amp;lt;br /&amp;gt;  == 사용법...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 개요 ==&lt;br /&gt;
Masonry와 비슷한 레이아웃을 보여주는 독구.(핀터레스트의 이미지 배치와 유사하다.)&lt;br /&gt;
&lt;br /&gt;
Masonry에 비해 사용이 쉽다.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 사용법 ==&lt;br /&gt;
&lt;br /&gt;
=== js ===&lt;br /&gt;
다음 코드의 출처는 https://velog.io/@hyeseong-dev/djangomagic-grid-articleapp&lt;br /&gt;
&lt;br /&gt;
아래 전체를 js파일로 만든다.&amp;lt;syntaxhighlight lang=&amp;quot;javascript+django&amp;quot;&amp;gt;&lt;br /&gt;
&amp;#039;use strict&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * @author emmanuelolaojo&lt;br /&gt;
 * @since 11/11/18&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Validates the configuration object.&lt;br /&gt;
 *&lt;br /&gt;
 * @param config - configuration object&lt;br /&gt;
 */&lt;br /&gt;
var checkParams = function (config) {&lt;br /&gt;
  var DEFAULT_GUTTER = 25;&lt;br /&gt;
  var booleanProps = [&amp;quot;useTransform&amp;quot;, &amp;quot;center&amp;quot;];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  if (!config) {&lt;br /&gt;
    throw new Error(&amp;quot;No config object has been provided.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for(var prop of booleanProps){&lt;br /&gt;
    if(typeof config[prop] !== &amp;quot;boolean&amp;quot;){&lt;br /&gt;
      config[prop] = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  if(typeof config.gutter !== &amp;quot;number&amp;quot;){&lt;br /&gt;
    config.gutter = DEFAULT_GUTTER;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (!config.container) { error(&amp;quot;container&amp;quot;); }&lt;br /&gt;
  if (!config.items &amp;amp;&amp;amp; !config.static) { error(&amp;quot;items or static&amp;quot;); }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Handles invalid configuration object&lt;br /&gt;
 * errors.&lt;br /&gt;
 *&lt;br /&gt;
 * @param prop - a property with a missing value&lt;br /&gt;
 */&lt;br /&gt;
var error = function (prop) {&lt;br /&gt;
  throw new Error((&amp;quot;Missing property &amp;#039;&amp;quot; + prop + &amp;quot;&amp;#039; in MagicGrid config&amp;quot;));&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Finds the shortest column in&lt;br /&gt;
 * a column list.&lt;br /&gt;
 *&lt;br /&gt;
 * @param cols - list of columns&lt;br /&gt;
 *&lt;br /&gt;
 * @return shortest column&lt;br /&gt;
 */&lt;br /&gt;
var getMin = function (cols) {&lt;br /&gt;
  var min = cols[0];&lt;br /&gt;
&lt;br /&gt;
  for (var col of cols) {&lt;br /&gt;
    if (col.height &amp;lt; min.height) { min = col; }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return min;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * @author emmanuelolaojo&lt;br /&gt;
 * @since 11/10/18&lt;br /&gt;
 *&lt;br /&gt;
 * The MagicGrid class is an&lt;br /&gt;
 * implementation of a flexible&lt;br /&gt;
 * grid layout.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
var MagicGrid = function MagicGrid (config) {&lt;br /&gt;
  checkParams(config);&lt;br /&gt;
&lt;br /&gt;
  if (config.container instanceof HTMLElement) {&lt;br /&gt;
    this.container = config.container;&lt;br /&gt;
    this.containerClass = config.container.className;&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    this.containerClass = config.container;&lt;br /&gt;
    this.container = document.querySelector(config.container);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  this.items = this.container.children;&lt;br /&gt;
  this.static = config.static || false;&lt;br /&gt;
  this.size = config.items;&lt;br /&gt;
  this.gutter = config.gutter;&lt;br /&gt;
  this.maxColumns = config.maxColumns || false;&lt;br /&gt;
  this.useMin = config.useMin || false;&lt;br /&gt;
  this.useTransform = config.useTransform;&lt;br /&gt;
  this.animate = config.animate || false;&lt;br /&gt;
  this.started = false;&lt;br /&gt;
  this.center = config.center;&lt;br /&gt;
&lt;br /&gt;
  this.init();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Initializes styles&lt;br /&gt;
 *&lt;br /&gt;
 * @private&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.init = function init () {&lt;br /&gt;
  if (!this.ready() || this.started) { return; }&lt;br /&gt;
&lt;br /&gt;
  this.container.style.position = &amp;quot;relative&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  for (var i = 0; i &amp;lt; this.items.length; i++) {&lt;br /&gt;
    var style = this.items[i].style;&lt;br /&gt;
&lt;br /&gt;
    style.position = &amp;quot;absolute&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    if (this.animate) {&lt;br /&gt;
      style.transition = (this.useTransform ? &amp;quot;transform&amp;quot; : &amp;quot;top, left&amp;quot;) + &amp;quot; 0.2s ease&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  this.started = true;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Calculates the width of a column.&lt;br /&gt;
 *&lt;br /&gt;
 * @return width of a column in the grid&lt;br /&gt;
 * @private&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.colWidth = function colWidth () {&lt;br /&gt;
  return this.items[0].getBoundingClientRect().width + this.gutter;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Initializes an array of empty columns&lt;br /&gt;
 * and calculates the leftover whitespace.&lt;br /&gt;
 *&lt;br /&gt;
 * @return {{cols: Array, wSpace: number}}&lt;br /&gt;
 * @private&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.setup = function setup () {&lt;br /&gt;
  var width = this.container.getBoundingClientRect().width;&lt;br /&gt;
  var colWidth = this.colWidth();&lt;br /&gt;
  var numCols = Math.floor(width/colWidth) || 1;&lt;br /&gt;
  var cols = [];&lt;br /&gt;
&lt;br /&gt;
  if (this.maxColumns &amp;amp;&amp;amp; numCols &amp;gt; this.maxColumns) {&lt;br /&gt;
    numCols = this.maxColumns;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for (var i = 0; i &amp;lt; numCols; i++) {&lt;br /&gt;
    cols[i] = {height: 0, index: i};&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var wSpace = width - numCols * colWidth + this.gutter;&lt;br /&gt;
&lt;br /&gt;
  return {cols: cols, wSpace: wSpace};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Gets the next available column.&lt;br /&gt;
 *&lt;br /&gt;
 * @param cols list of columns&lt;br /&gt;
 * @param i index of dom element&lt;br /&gt;
 *&lt;br /&gt;
 * @return {*} next available column&lt;br /&gt;
 * @private&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.nextCol = function nextCol (cols, i) {&lt;br /&gt;
  if (this.useMin) {&lt;br /&gt;
    return getMin(cols);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return cols[i % cols.length];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Positions each item in the grid, based&lt;br /&gt;
 * on their corresponding column&amp;#039;s height&lt;br /&gt;
 * and index then stretches the container to&lt;br /&gt;
 * the height of the grid.&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.positionItems = function positionItems () {&lt;br /&gt;
  var ref = this.setup();&lt;br /&gt;
    var cols = ref.cols;&lt;br /&gt;
    var wSpace = ref.wSpace;&lt;br /&gt;
  var maxHeight = 0;&lt;br /&gt;
  var colWidth = this.colWidth();&lt;br /&gt;
&lt;br /&gt;
  wSpace = this.center ? Math.floor(wSpace / 2) : 0;&lt;br /&gt;
&lt;br /&gt;
  for (var i = 0; i &amp;lt; this.items.length; i++) {&lt;br /&gt;
    var col = this.nextCol(cols, i);&lt;br /&gt;
    var item = this.items[i];&lt;br /&gt;
    var topGutter = col.height ? this.gutter : 0;&lt;br /&gt;
    var left = col.index * colWidth + wSpace + &amp;quot;px&amp;quot;;&lt;br /&gt;
    var top = col.height + topGutter + &amp;quot;px&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    if(this.useTransform){&lt;br /&gt;
      item.style.transform = &amp;quot;translate(&amp;quot; + left + &amp;quot;, &amp;quot; + top + &amp;quot;)&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
      item.style.top = top;&lt;br /&gt;
      item.style.left = left;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    col.height += item.getBoundingClientRect().height + topGutter;&lt;br /&gt;
&lt;br /&gt;
    if(col.height &amp;gt; maxHeight){&lt;br /&gt;
      maxHeight = col.height;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  this.container.style.height = maxHeight + this.gutter + &amp;quot;px&amp;quot;;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Checks if every item has been loaded&lt;br /&gt;
 * in the dom.&lt;br /&gt;
 *&lt;br /&gt;
 * @return {Boolean} true if every item is present&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.ready = function ready () {&lt;br /&gt;
  if (this.static) { return true; }&lt;br /&gt;
  return this.items.length &amp;gt;= this.size;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Periodically checks that all items&lt;br /&gt;
 * have been loaded in the dom. Calls&lt;br /&gt;
 * this.listen() once all the items are&lt;br /&gt;
 * present.&lt;br /&gt;
 *&lt;br /&gt;
 * @private&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.getReady = function getReady () {&lt;br /&gt;
    var this$1 = this;&lt;br /&gt;
&lt;br /&gt;
  var interval = setInterval(function () {&lt;br /&gt;
    this$1.container = document.querySelector(this$1.containerClass);&lt;br /&gt;
    this$1.items = this$1.container.children;&lt;br /&gt;
&lt;br /&gt;
    if (this$1.ready()) {&lt;br /&gt;
      clearInterval(interval);&lt;br /&gt;
&lt;br /&gt;
      this$1.init();&lt;br /&gt;
      this$1.listen();&lt;br /&gt;
    }&lt;br /&gt;
  }, 100);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Positions all the items and&lt;br /&gt;
 * repositions them whenever the&lt;br /&gt;
 * window size changes.&lt;br /&gt;
 */&lt;br /&gt;
MagicGrid.prototype.listen = function listen () {&lt;br /&gt;
    var this$1 = this;&lt;br /&gt;
&lt;br /&gt;
  if (this.ready()) {&lt;br /&gt;
    var timeout;&lt;br /&gt;
&lt;br /&gt;
    window.addEventListener(&amp;quot;resize&amp;quot;, function () {&lt;br /&gt;
      if (!timeout){&lt;br /&gt;
        timeout = setTimeout(function () {&lt;br /&gt;
          this$1.positionItems();&lt;br /&gt;
          timeout = null;&lt;br /&gt;
        }, 200);&lt;br /&gt;
      }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    this.positionItems();&lt;br /&gt;
  }&lt;br /&gt;
  else { this.getReady(); }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
let magicGrid = new MagicGrid({&lt;br /&gt;
container: &amp;#039;.container&amp;#039;,&lt;br /&gt;
animate: true,&lt;br /&gt;
gutter: 30,&lt;br /&gt;
static: true,&lt;br /&gt;
useMin: true&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
var masonrys = document.getElementsByTagName(&amp;quot;img&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
for (let i = 0; i &amp;lt; masonrys.length; i++){&lt;br /&gt;
    masonrys[i].addEventListener(&amp;#039;load&amp;#039;, function(){&lt;br /&gt;
        magicGrid.positionItems();&lt;br /&gt;
    }, false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
magicGrid.listen();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;각각의 개체들이 움직이는 속도는 style.transition 의 시간을 조정하면 되고, 개체들 사이의 간격은 마지막 gutter의 숫자를 조정하면 된다.&lt;br /&gt;
&lt;br /&gt;
=== html ===&lt;br /&gt;
&lt;br /&gt;
==== 스타일에 대한 코드 ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css+django&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
.container div { /* container클래스 안의 div 태그에 적용되는 것. */&lt;br /&gt;
  width: 250px;&lt;br /&gt;
  background-color: antiquewhite;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  justify-content: center;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  border-radius: 1rem;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
  .container img {&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;css코드로 적절하게 내부 요소에 대한 style을 지정하면 된다.&lt;br /&gt;
&lt;br /&gt;
==== 본문에 사용할 코드 ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html+django&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;div&amp;gt;&lt;br /&gt;
        &amp;lt;img src=&amp;quot;https://picsum.photos/200/300&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;div&amp;gt;&lt;br /&gt;
        &amp;lt;img src=&amp;quot;https://picsum.photos/200/340&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/div&amp;gt;&lt;br /&gt;
      ......&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;이들 이후에 &amp;lt;code&amp;gt;&amp;lt;script src=&amp;quot;{% static &amp;#039;invitation/magicgrid.js&amp;#039; %}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/code&amp;gt;같은 형식으로 스크립트 파일을 불러와야 제대로 작동한다.&lt;br /&gt;
[[분류:웹]]&lt;/div&gt;</summary>
		<author><name>Sam</name></author>
	</entry>
</feed>