画面の右下のハートをタップ(クリック)すると小さいハートが飛び広がります
コードエディター 本文
<div id="heart-fixed-trigger" class="custom-heart-fixed">
<svg viewBox="0 -20 150 120" class="heart-svg"> /* ハートを表示する範囲のサイズ */
<path class="h-line back" d="M50,88.9L44.1,83.5C23.1,64.5,9.2,51.8,9.2,36.2c0-12.7,10-22.7,22.7-22.7c7.2,0,14,3.3,18.1,8.6 c4.1-5.3,11-8.6,18.1-8.6c12.7,0,22.7,10,22.7,22.7c0,15.6-13.9,28.3-34.9,47.3L50,88.9z" transform="translate(50, -23)" /* ハートの重なり具合を指定 */ />
<path class="h-line front" d="M50,88.9L44.1,83.5C23.1,64.5,9.2,51.8,9.2,36.2c0-12.7,10-22.7,22.7-22.7c7.2,0,14,3.3,18.1,8.6 c4.1-5.3,11-8.6,18.1-8.6c12.7,0,22.7,10,22.7,22.7c0,15.6-13.9,28.3-34.9,47.3L50,88.9z" />
</svg>
</div>
カスタムJavaScript
(function() {
const trigger = document.getElementById('heart-fixed-trigger');
if (!trigger) return;
/* 飛び散るハートの色を指定 */
const colors = ['#ffb6c1', '#ffebef', '#ffd1dc', '#ffb7c5', '#f8d7da'];
function createParticle(x, y) {
const p = document.createElement('div');
p.className = 'p-heart';
p.innerHTML = '♥';
p.style.color = colors[Math.floor(Math.random() * colors.length)];
const size = Math.floor(Math.random() * 15) + 12;
p.style.fontSize = size + 'px';
const duration = Math.random() * 0.4 + 0.6;
p.style.animationDuration = duration + 's';
const tx = (Math.random() - 0.5) * 200;
const ty = (Math.random() - 0.5) * 200;
p.style.setProperty('--tx', tx + 'px');
p.style.setProperty('--ty', ty + 'px');
p.style.left = x + 'px';
p.style.top = y + 'px';
document.body.appendChild(p);
setTimeout(() => {
p.remove();
}, duration * 1000);
}
// イベント登録
const handleAction = function(e) {
if (e.type === 'touchstart') e.preventDefault();
const rect = trigger.getBoundingClientRect();
const cX = rect.left + (rect.width / 2);
const cY = rect.top + (rect.height / 2);
for (let i = 0; i < 12; i++) {
createParticle(cX, cY);
}
};
trigger.addEventListener('mousedown', handleAction);
trigger.addEventListener('touchstart', handleAction, {passive: false});
})();
カスタムCSS
/* 固定ハートのスタイル */
.custom-heart-fixed {
position: fixed;
bottom: 30px;/* ハートの画面下からの位置 */
right: 20px;/* ハートの画面右からの位置 */
width: 40px;/* ハートの横幅 */
height: 40px;/* ハートの縦の長さ */
z-index: 99999;
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
.heart-svg { width: 100%; height: 100%; pointer-events: none; }
.h-line {
fill: none;
stroke: #ffb6c1; /* ハートの色 */
stroke-width: 5; /* ハートの太さ */
stroke-linecap: round;
stroke-linejoin: round;
}
/* 背面のハートを少しだけ薄くして重なりを強調(お好みで 1 にしてもOK) */
.h-line.back {
opacity: 0.8;
}
/* 飛び散るハート */
.p-heart {
position: fixed;
pointer-events: none;
user-select: none;
z-index: 100000;
--tx: 0px;
--ty: 0px;
animation: explodeHeart 0.8s ease-out forwards;
}
@keyframes explodeHeart {
0% {
transform: translate(-50%, -50%) scale(0) rotate(0deg);
opacity: 1;
}
100% {
transform: translate(calc(-50% + var(--tx)), calc(-50% + var(--ty))) scale(1.2) rotate(360deg);
opacity: 0;
}
}

