jQueryの基本概念
jQueryは、DOM要素の選択と操作を簡素化する強力なライブラリである。例えば、id属性がtargetElの要素を選択するには、以下のように記述する。
const $element = $("#targetEl");
選択された要素はjQueryオブジェクトとしてラップされる。メソッドの多くは引数の有無によってゲッターとセッターの両方として機能する。幅を取得する場合はwidth()を引数なしで呼び出し、設定する場合は数値を渡す。
// 幅の取得
const currentWidth = $element.width();
// 幅の設定
$element.width(500);
スライドパズルの実装
jQuery UIのdraggableを活用し、画像を分割したピースをスライドさせるパズルを構築する。
ピースの生成と配置
元画像をグリッド状に分割し、各ピースをdiv要素として生成する。背景画像をずらすことで、一つの画像を複数のピースに見せかける。
const GRID_COL = 3;
const GRID_ROW = 4;
const $puzzleContainer = $("#puzzle-board");
const $sourceImg = $puzzleContainer.find("img");
const imgSrc = $sourceImg.attr("src");
const pieceWidth = Math.floor($sourceImg.width() / GRID_COL);
const pieceHeight = Math.floor($sourceImg.height() / GRID_ROW);
$sourceImg.remove();
for (let r = 0; r < GRID_ROW; r++) {
for (let c = 0; c < GRID_COL; c++) {
const offsetX = pieceWidth * c;
const offsetY = pieceHeight * r;
$("<div/>").css({
width: pieceWidth,
height: pieceHeight,
position: "absolute",
left: offsetX,
top: offsetY,
backgroundImage: `url(${imgSrc})`,
backgroundPosition: `-${offsetX}px -${offsetY}px`
}).appendTo($puzzleContainer);
}
}
シャッフルとドラッグ制御
ピースをランダムに配置するためのFisher-Yatesアルゴリズムを実装し、空白スペースに隣接するピースのみが移動できるようにdraggableの挙動を制御する。
function randomizeItems(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
let $pieces = $puzzleContainer.children();
randomizeItems($pieces);
$pieces.draggable({
containment: "parent",
grid: [pieceWidth, pieceHeight],
start: function(e, ui) {
// ドラッグ開始時の制御ロジック
// 空白スペースと同じ行または列か判定し、軸を制限する
}
});
クリア判定とタイム記録
ピースが全て正しい位置に移動したかを確認し、クリア時にかかった時間をlocalStorageに保存する。
function checkClearState() {
let matchedCount = 0;
$pieces.each(function(index) {
const $el = $(this);
const currentPos = {
top: parseInt($el.css("top")),
left: parseInt($el.css("left"))
};
if (currentPos.top === correctPositions[index].top && currentPos.left === correctPositions[index].left) {
matchedCount++;
}
});
if (matchedCount === $pieces.length) {
clearInterval(gameTimer);
const totalTime = (elapsedTime.hours * 3600) + (elapsedTime.minutes * 60) + elapsedTime.seconds;
const storedBest = localStorage.getItem("puzzleBest");
if (!storedBest || totalTime < parseInt(storedBest)) {
localStorage.setItem("puzzleBest", totalTime);
$("<p/>", { text: "新しいベストタイムです!" }).appendTo("#game-ui");
}
}
}
スクロール追従型サイドバーの構築
CSSのposition: fixedはドキュメント全体を基準とするため、レイアウトによっては崩れが生じる。jQueryを用いてスクロール量を監視し、特定の位置までは静的に、超えた場合は固定として振る舞わせることで解決する。
位置の固定とリサイズ対応
const $navAside = $("aside");
const initialOffset = $navAside.offset();
const $windowObj = $(window);
$windowObj.on("scroll", function() {
if ($windowObj.scrollTop() > initialOffset.top) {
$navAside.css({
position: "fixed",
top: 0,
left: initialOffset.left
});
} else {
$navAside.css({
position: "static"
});
}
});
$windowObj.on("resize", function() {
// リサイズ時にleft位置などを再計算
const wrapperLeft = $(".wrapper").offset().left;
$navAside.css("left", wrapperLeft);
});
スムーズスクロールとハッシュ制御
ナビゲーションリンクのクリック時に、アニメーションで対象セクションまでスクロールさせる。また、hashchangeイベントを監視し、ブラウザの戻るボタンにも対応させる。
function animateScrollTo(targetOffset, hashVal) {
$("html, body").animate({ scrollTop: targetOffset }, 400, function() {
if (hashVal) window.location.hash = hashVal;
});
}
$navAside.on("click", "a", function(e) {
e.preventDefault();
const targetId = $(this).attr("href");
const targetTop = $(targetId).offset().top;
animateScrollTo(targetTop, targetId);
});
$windowObj.on("hashchange", function() {
const currentHash = window.location.hash;
if (currentHash) {
const targetTop = $(currentHash).offset().top;
animateScrollTo(targetTop, currentHash);
}
});
インタラクティブなGoogleマップの作成
Google Maps APIとjQueryを組み合わせ、マーカーの配置、住所の逆ジオコーディング、距離計算を行うアプリケーションを構築する。
地図の初期化とカスタムオーバーレイ
地図を描画し、会社の本社などを示すカスタムマーカーと情報ウィンドウを追加する。
const gMaps = google.maps;
const mapCenter = new gMaps.LatLng(35.681236, 139.767125);
const mapConfig = {
zoom: 14,
center: mapCenter,
mapTypeId: gMaps.MapTypeId.ROADMAP
};
const mapInstance = new gMaps.Map(document.getElementById("map-canvas"), mapConfig);
const hqMarker = new gMaps.Marker({
position: mapCenter,
map: mapInstance,
icon: "img/hq_icon.png"
});
const infoPanel = new gMaps.InfoWindow({
content: document.getElementById("hq-details")
});
gMaps.event.addListener(hqMarker, "click", function() {
infoPanel.open(mapInstance, hqMarker);
});
地点の追加と住所の取得
地図のクリックイベントからマーカーを追加し、ジオコーダーで住所を取得してUIを更新する。
let clickCounter = 0;
const geoCoder = new gMaps.Geocoder();
gMaps.event.addListener(mapInstance, "click", function(event) {
if (clickCounter >= 2) return;
const markerOpts = {
map: mapInstance,
position: event.latLng,
draggable: true
};
const newMarker = new gMaps.Marker(markerOpts);
geoCoder.geocode({ latLng: event.latLng }, function(results) {
const address = results[0].formatted_address;
// jQueryでUIに住所を表示
});
clickCounter++;
});
距離と料金の計算
距離行列サービスを利用して2点間の移動距離を算出し、料金を計算して表示する。
const distService = new gMaps.DistanceMatrixService();
distService.getDistanceMatrix({
origins: [startLatLng],
destinations: [endLatLng],
travelMode: gMaps.TravelMode.DRIVING
}, function(response) {
const distText = response.rows[0].elements[0].distance.text;
const distVal = parseFloat(distText);
// 距離と重量から料金を算出しUIに反映
});