本日1件のお問い合わせがありました。

✉️FIELDにお問い合わせ

Uncategorized

特定領域だけふわふわと自社CTAが上がってくるjavascript

記事中に常に表示される「お問い合わせ」などの固定フローティングボタン。便利な一方で、競合他社紹介エリアなど特定セクションでは非表示にしたいケースもあります。本記事では、記事内の特定要素(id="huwastart"id="huwaend")の間にスクロール位置が入ったときだけ、自社ボタンを“ふわふわ”と上下に動かしながら表示/非表示を切り替える実装手法をご紹介します。


課題と要件整理

  1. 常時固定表示
    通常は画面下部に position: fixed されたボタンを表示しておく。
  2. 競合エリアではオフ
    記事中に「他社紹介エリア」を設置し、その範囲では自社ボタンを非表示(もしくは別挙動)にしたい。
  3. 動的アニメーション
    競合エリアに入った瞬間から“ふわふわ”浮遊アニメーションを開始。エリア外に出たらアニメーション停止して元位置にリセット。
  4. デバッグログ
    挙動確認のため、スクロール位置や要素検出状況をコンソールログに出力。

HTML/CSS 構造イメージ

<!-- 固定ボタン -->
<div class="column_detail_fix_btn_wrap">
<!-- 内部構造省略 -->
</div>

<!-- 記事中の競合紹介エリア -->
<div id="huwastart"></div>
<!-- ここに他社情報が並ぶ -->
<div id="huwaend"></div>
.column_detail_fix_btn_wrap {
position: fixed;
z-index: 50;
left: 0;
bottom: 0;
width: 100%;
background-color: rgba(255, 255, 255, 0);
padding: 0 0 8px;
/* transform は JS で制御 */
}

JavaScript 実装のポイント

  1. DOMContentLoaded で確実に DOM を取得
  2. getElementPosition() で要素の絶対位置(ドキュメントトップからのオフセット)を計算
  3. window.addEventListener('scroll', …) でスクロールごとに位置判定
  4. 範囲内判定後、requestAnimationFrame によるサイン波ベースのアニメーション
  5. ログ出力で各種パラメータ(スクロール位置/要素位置/アニメーション状態)を可視化

コード全文

<script>
(function() {
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM読み込み完了 - ふわふわアニメーション初期化開始');

const floatingBtn = document.querySelector('.column_detail_fix_btn_wrap');
const startMarker = document.getElementById('huwastart');
const endMarker = document.getElementById('huwaend');

console.log('要素検出状況:', {
floatingBtn: !!floatingBtn,
startMarker: !!startMarker,
endMarker: !!endMarker
});
if (!floatingBtn || !startMarker || !endMarker) {
console.error('必要な要素が見つかりません。処理を中止します。');
return;
}

function getElementPosition(el) {
let pos = 0;
while (el) {
pos += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return pos;
}

let isAnimating = false, animationId = null, time = 0;
const speed = 0.005;

function checkScrollPosition() {
const scrollY = window.scrollY || window.pageYOffset;
const startY = getElementPosition(startMarker);
const endY = getElementPosition(endMarker);
const inArea = scrollY >= startY && scrollY <= endY;

console.log('スクロール位置チェック:', {scrollY, startY, endY, inArea});

if (inArea && !isAnimating) {
startAnimation();
} else if (!inArea && isAnimating) {
stopAnimation();
}
}

function startAnimation() {
isAnimating = true;
time = 0;
console.log('アニメーション開始');

function animate() {
time += speed;
const sine = Math.sin(time);
const vh = window.innerHeight;
const maxPixels = vh * 0.3;
const yOffset = (sine + 1) / 2 * maxPixels;
floatingBtn.style.transform = `translateY(-${yOffset}px)`;

animationId = requestAnimationFrame(animate);
}
animate();
}

function stopAnimation() {
isAnimating = false;
console.log('アニメーション停止 - 位置リセット');
if (animationId) cancelAnimationFrame(animationId);
floatingBtn.style.transform = '';
}

window.addEventListener('scroll', checkScrollPosition);
console.log('初期スクロールチェック開始');
setTimeout(checkScrollPosition, 500);
});
})();
</script>

詳細解説

  • getElementPosition のロジック
    要素の相対的な offsetTop を親要素ごとに加算し、ドキュメント上の絶対 Y 座標を算出。スクロール位置と比較するのに用います。
  • サイン波アニメーション
    Math.sin(time)-1~1 の周期関数。そのままだと負値も出るため、(sine+1)/20~1 に正規化し、画面高さの 0~30% の範囲で上下運動を実現。
  • パフォーマンス配慮
    画面更新ごとに大量ログを吐くと重くなるため、Math.floor(time*10)%20===0 といった条件で間引きログ。
  • デバッグログ
    ・要素検出状況
    ・スクロールチェック時の各種座標
    ・アニメーション開始/停止イベント
    →本番運用ではコメントアウトまたは console.debug に置き換えると良いでしょう。

応用とカスタマイズ

  • 対象エリアを複数設置
    複数の開始/終了マーカーを配列で管理し、どのエリアにいるかループで判定可能。
  • 表示・非表示切り替え
    アニメーションだけでなく、CSS クラス切り替えで完全に非表示にも応用可能。
  • レスポンシブ対応
    画面幅によって maxPixelsspeed を調整し、モバイルではゆっくり、PCでは高速に動かすなど。

まとめ

この記事では、

  • 記事内の特定範囲のみ挙動を変えたい
  • 固定要素(position: fixed)に対してスクロール連動アニメーションを実装したい

といったニーズを満たすための JavaScript テクニックをご紹介しました。スクロール位置の取得からサイン波アニメーション、デバッグログまでワンストップで実装例を示しています。ぜひ皆さんのサイトでも「あるけど意外とない」動的なフローティングボタンをお試しください!
>>こちらの記事にスクリプトで埋められています。

Yamamoto Yuya

プロフェッショナルとしての高いスキルと知識を持ち、誠実さと責任感を大切にする。常に向上心を持ち、新たな挑戦にも積極的に取り組む努力家。