メニュー

東京・小金井市のWEB制作会社の豆知識

MEMORANDUM

jQueryで画像をランダムにばら撒いたように配置する

以前、飲食店サイトを制作した際に、記念写真を掲載する目的でメインビューに使っていたスクリプトを思い出しのたのでメモ。
卓上に写真を広げるような感じでレイアウトでき、ドラッグ操作で動かせるので、一覧表示と比べると若干の見づらさはあるものの、目的のものを探し出す体験も含めて、一定の効果はありそうです。

HTML

<ul id="photo-list">
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
<li><a href=""><img src="○○.jpg" alt="○○"></a></li>
</ul>

CSS

#photo-list {
	position: relative;
	width: 100%;
	height: 100vh;
	margin: 0 auto;
	padding: 0;
	background: #f5f5f5;
	overflow: hidden;
}
#photo-list li {
	list-style: none;
	position: absolute;
	width: 25vw; /* 親幅に応じて自動調整 */
	left: 100vw;
}
#photo-list li:active {
	cursor: grabbing;
}
#photo-list li img {
	width: 100%;
	display: block;
	box-shadow: 0 4px 10px rgba(0,0,0,0.3);
	border-radius: 6px;
	transition: transform 0.8s ease-out;
	user-select: none;
}

jQuery

var $items = $('#photo-list li');
var $container = $('#photo-list');
var zIndexCounter = 1;

function getAreaSize() {
	return { width: $container.width(), height: $container.height() };
}

function getItemSize($el) {
	return { width: $el.width(), height: $el.height() };
}

// 初期位置:右外からばらまく
$items.each(function() {
	var area = getAreaSize();
	var item = getItemSize($(this));
	$(this).css({
		left: area.width + 200,
		top: area.height / 2 - item.height / 2,
		opacity: 0,
		transform: 'rotate(0deg) scale(0.8)'
	});
});

// ばらまきアニメーション
setTimeout(() => {
	$items.each(function() {
		var area = getAreaSize();
		var item = getItemSize($(this));
		var left = Math.random() * (area.width - item.width);
		var top = Math.random() * (area.height - item.height);
		var rotate = (Math.random() * 60) - 30;
		var delay = Math.random() * 800;

		$(this).delay(delay).animate({
			left: left,
			top: top,
			opacity: 1
		}, {
			duration: 1000,
			easing: 'swing',
			step: function(_, fx) {
				$(this).css('transform', `rotate(${rotate}deg) scale(1)`);
			}
		});
	});
}, 500);

if ($(window).width() < 980) {

	// スマホ・タブレット用ドラッグ
	$items.on({
		touchstart: function(e) {
			var $this = $(this);
			var touch = e.originalEvent.touches[0];

			$this.data({
				startX: touch.pageX,
				startY: touch.pageY,
				offsetX: touch.pageX - $this.position().left - $container.offset().left,
				offsetY: touch.pageY - $this.position().top - $container.offset().top,
				isDragging: false,
				dragOccurred: false
			});

			zIndexCounter++;
			$this.css('z-index', zIndexCounter);
		},

		touchmove: function(e) {
			var $this = $(this);
			var touch = e.originalEvent.touches[0];
			var startX = $this.data('startX');
			var startY = $this.data('startY');
			var offsetX = $this.data('offsetX');
			var offsetY = $this.data('offsetY');
			var isDragging = $this.data('isDragging');
			var dragOccurred = $this.data('dragOccurred');
			var dragThreshold = 5;

			var deltaX = Math.abs(touch.pageX - startX);
			var deltaY = Math.abs(touch.pageY - startY);

			if (!isDragging && (deltaX > dragThreshold || deltaY > dragThreshold)) {
				isDragging = true;
				dragOccurred = true;
			}

			if (isDragging) {
				e.preventDefault();
				$this.css({
					left: touch.pageX - $container.offset().left - offsetX + 'px',
					top: touch.pageY - $container.offset().top - offsetY + 'px'
				});
			}

			$this.data({
				isDragging: isDragging,
				dragOccurred: dragOccurred
			});
		},

		touchend: function(e) {
			var $this = $(this);
			var dragOccurred = $this.data('dragOccurred');
			if (dragOccurred) e.preventDefault();

			$this.removeData('isDragging dragOccurred startX startY offsetX offsetY');
		}
	});

} else {

	// PC用ドラッグ
	$items.on('mousedown', function(e) {
		var $this = $(this);
		e.preventDefault();
		var startX = e.pageX;
		var startY = e.pageY;
		var offsetX = startX - $this.position().left - $container.offset().left;
		var offsetY = startY - $this.position().top - $container.offset().top;
		var isDragging = false;
		var dragThreshold = 3;
		var dragOccurred = false;

		zIndexCounter++;
		$this.css('z-index', zIndexCounter);

		function clickPreventer(e) {
			e.preventDefault();
		}

		function mouseMoveHandler(e) {
			var deltaX = Math.abs(e.pageX - startX);
			var deltaY = Math.abs(e.pageY - startY);

			if (!isDragging && (deltaX > dragThreshold || deltaY > dragThreshold)) {
				isDragging = true;
				dragOccurred = true;
				$this.find('a').on('click.prevent', clickPreventer);
			}

			if (isDragging) {
				$this.css({
					left: e.pageX - $container.offset().left - offsetX + 'px',
					top: e.pageY - $container.offset().top - offsetY + 'px'
				});
			}
		}

		function mouseUpHandler(e) {
			$(document).off('mousemove', mouseMoveHandler);
			$(document).off('mouseup', mouseUpHandler);

			if (dragOccurred) {
				$this.one('click', function(e) {
					e.preventDefault();
				});
				$this.find('a').off('click.prevent', clickPreventer);
			}
		}

		$(document).on('mousemove', mouseMoveHandler);
		$(document).on('mouseup', mouseUpHandler);
	});
}

SAMPLE

  • 建設|東京のホームページ制作実績
  • 転職・就職|東京のホームページ制作実績
  • 保険|東京のホームページ制作実績
  • 商社|東京のホームページ制作実績
  • 旅行|東京のホームページ制作実績
  • スキンケア・ボディケア・サプリメント|東京のホームページ制作実績
  • 子育て|東京のホームページ制作実績
  • 就労継続支援|埼玉県のホームページ制作実績
  • 防犯・防災設備|東京・小平市のホームページ制作実績
  • 水道設備|神奈川県のホームページ制作実績
RANKING

人気記事

同一カテゴリーの記事