728x90
반응형
MagicGrid
- 카드형 레이아웃 제공
- 아래 Magic-Grid github 주소로 html, js, css 코드 복사
https://github.com/e-oj/Magic-Grid
articleapp 생성
python manage.py startapp articleapp
settings.py 추가
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap4',
'accountapp',
'profileapp',
'articleapp',
]
- 생성한 articleapp 앱 추가
메인 urls.py 추가
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from pragmatic import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accountapp.urls')),
path('profiles/', include('profileapp.urls')),
path('articles/', include('articleapp.urls')),
# 미디어 사진 출력하기 위한 MEDIA 환경 설정 추가
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- articleapp url 주소 추가
urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('list/', TemplateView.as_view(template_name='articleapp/list.html'), name='list'),
]
- articleapp의 urls.py 생성
- 장고가 제공하는 TemplateView 설정, list.html로 지정
- 템플릿만 지정해주면 장고가 알아서 만들어줌
/static/magicgrid.js
'use strict';
/**
* @author emmanuelolaojo
* @since 11/11/18
*/
/**
* Validates the configuration object.
*
* @param config - configuration object
*/
var checkParams = function (config) {
var DEFAULT_GUTTER = 25;
var booleanProps = ["useTransform", "center"];
if (!config) {
throw new Error("No config object has been provided.");
}
for(var prop of booleanProps){
if(typeof config[prop] !== "boolean"){
config[prop] = true;
}
}
if(typeof config.gutter !== "number"){
config.gutter = DEFAULT_GUTTER;
}
if (!config.container) { error("container"); }
if (!config.items && !config.static) { error("items or static"); }
};
/**
* Handles invalid configuration object
* errors.
*
* @param prop - a property with a missing value
*/
var error = function (prop) {
throw new Error(("Missing property '" + prop + "' in MagicGrid config"));
};
/**
* Finds the shortest column in
* a column list.
*
* @param cols - list of columns
*
* @return shortest column
*/
var getMin = function (cols) {
var min = cols[0];
for (var col of cols) {
if (col.height < min.height) { min = col; }
}
return min;
};
/**
* @author emmanuelolaojo
* @since 11/10/18
*
* The MagicGrid class is an
* implementation of a flexible
* grid layout.
*/
var MagicGrid = function MagicGrid (config) {
checkParams(config);
if (config.container instanceof HTMLElement) {
this.container = config.container;
this.containerClass = config.container.className;
}
else {
this.containerClass = config.container;
this.container = document.querySelector(config.container);
}
this.items = this.container.children;
this.static = config.static || false;
this.size = config.items;
this.gutter = config.gutter;
this.maxColumns = config.maxColumns || false;
this.useMin = config.useMin || false;
this.useTransform = config.useTransform;
this.animate = config.animate || false;
this.started = false;
this.center = config.center;
this.init();
};
/**
* Initializes styles
*
* @private
*/
MagicGrid.prototype.init = function init () {
if (!this.ready() || this.started) { return; }
this.container.style.position = "relative";
for (var i = 0; i < this.items.length; i++) {
var style = this.items[i].style;
style.position = "absolute";
if (this.animate) {
style.transition = (this.useTransform ? "transform" : "top, left") + " 0.2s ease";
}
}
this.started = true;
};
/**
* Calculates the width of a column.
*
* @return width of a column in the grid
* @private
*/
MagicGrid.prototype.colWidth = function colWidth () {
return this.items[0].getBoundingClientRect().width + this.gutter;
};
/**
* Initializes an array of empty columns
* and calculates the leftover whitespace.
*
* @return {{cols: Array, wSpace: number}}
* @private
*/
MagicGrid.prototype.setup = function setup () {
var width = this.container.getBoundingClientRect().width;
var colWidth = this.colWidth();
var numCols = Math.floor(width/colWidth) || 1;
var cols = [];
if (this.maxColumns && numCols > this.maxColumns) {
numCols = this.maxColumns;
}
for (var i = 0; i < numCols; i++) {
cols[i] = {height: 0, index: i};
}
var wSpace = width - numCols * colWidth + this.gutter;
return {cols: cols, wSpace: wSpace};
};
/**
* Gets the next available column.
*
* @param cols list of columns
* @param i index of dom element
*
* @return {*} next available column
* @private
*/
MagicGrid.prototype.nextCol = function nextCol (cols, i) {
if (this.useMin) {
return getMin(cols);
}
return cols[i % cols.length];
};
/**
* Positions each item in the grid, based
* on their corresponding column's height
* and index then stretches the container to
* the height of the grid.
*/
MagicGrid.prototype.positionItems = function positionItems () {
var ref = this.setup();
var cols = ref.cols;
var wSpace = ref.wSpace;
var maxHeight = 0;
var colWidth = this.colWidth();
wSpace = this.center ? Math.floor(wSpace / 2) : 0;
for (var i = 0; i < this.items.length; i++) {
var col = this.nextCol(cols, i);
var item = this.items[i];
var topGutter = col.height ? this.gutter : 0;
var left = col.index * colWidth + wSpace + "px";
var top = col.height + topGutter + "px";
if(this.useTransform){
item.style.transform = "translate(" + left + ", " + top + ")";
}
else{
item.style.top = top;
item.style.left = left;
}
col.height += item.getBoundingClientRect().height + topGutter;
if(col.height > maxHeight){
maxHeight = col.height;
}
}
this.container.style.height = maxHeight + this.gutter + "px";
};
/**
* Checks if every item has been loaded
* in the dom.
*
* @return {Boolean} true if every item is present
*/
MagicGrid.prototype.ready = function ready () {
if (this.static) { return true; }
return this.items.length >= this.size;
};
/**
* Periodically checks that all items
* have been loaded in the dom. Calls
* this.listen() once all the items are
* present.
*
* @private
*/
MagicGrid.prototype.getReady = function getReady () {
var this$1 = this;
var interval = setInterval(function () {
this$1.container = document.querySelector(this$1.containerClass);
this$1.items = this$1.container.children;
if (this$1.ready()) {
clearInterval(interval);
this$1.init();
this$1.listen();
}
}, 100);
};
/**
* Positions all the items and
* repositions them whenever the
* window size changes.
*/
MagicGrid.prototype.listen = function listen () {
var this$1 = this;
if (this.ready()) {
var timeout;
window.addEventListener("resize", function () {
if (!timeout){
timeout = setTimeout(function () {
this$1.positionItems();
timeout = null;
}, 200);
}
});
this.positionItems();
}
else { this.getReady(); }
};
let magicGrid = new MagicGrid({
container: '.container',
animate: true,
gutter: 30,
static: true,
useMin: true
});
// js 추가, 이미지 레이아웃 형태 변경
// 새로고침 할때마다 레이아웃 재배치가 일어남
var masonrys = document.getElementsByTagName("img");
for (let i = 0; i < masonrys.length; i++){
masonrys[i].addEventListener('load', function() {
magicGrid.positionItems();
}, false);
}
magicGrid.listen();
- magic-grid의 Javascript 복사 후 static 폴더에 js파일 지정
- 추가로 이미지 레이아웃 재배치 설정 js 추가
Picsum
- 이미지 랜덤으로 제공해주는 사이트
- url 주소로 요청을 보내면 랜덤한 이미지 보여줌
list.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<style>
.container div {
width: 250px;
background-color: antiquewhite;
display: flex;
justify-content: center;
align-items: center;
border-radius: 1rem;
}
.container img{
width: 100%;
border-radius: 1rem;
}
</style>
<div class="container">
<div >
<img src="https://picsum.photos/200/300">
</div>
<div >
<img src="https://picsum.photos/200/340">
</div>
<div >
<img src="https://picsum.photos/200/260">
</div>
<div >
<img src="https://picsum.photos/200/400">
</div>
<div >
<img src="https://picsum.photos/200/300">
</div>
<div >
<img src="https://picsum.photos/200/250">
</div>
<div >
<img src="https://picsum.photos/200/200">
</div>
<div >
<img src="https://picsum.photos/200/440">
</div>
<div >
<img src="https://picsum.photos/200/300">
</div>
<div >
<img src="https://picsum.photos/200/200">
</div>
<div >
<img src="https://picsum.photos/200/350">
</div>
<div >
<img src="https://picsum.photos/200/430">
</div>
<div >
<img src="https://picsum.photos/200/300">
</div>
<div >
<img src="https://picsum.photos/200/400">
</div>
<div >
<img src="https://picsum.photos/200/280">
</div>
</div>
<script src="{% static 'js/magicgrid.js' %}"></script>
{% endblock %}
- magic-grid html 소스 복사 붙여넣기
- static/js 파일 경로 추가
- picsum의 이미지 추가
페이지 화면
- 새로고침 시 랜덤으로 사진 변경
반응형
'Backend > Django' 카테고리의 다른 글
django 24. ListView, Pagination 소개 및 적용 (0) | 2021.10.10 |
---|---|
django 23. Articleapp 구현 (0) | 2021.10.10 |
django 21. get_success_url 함수 그리고 리팩토링 (0) | 2021.10.06 |
django 20. Profileapp 마무리 (0) | 2021.10.06 |
django 19. Profileapp 구현 시작 (0) | 2021.10.06 |