Skip to content

Instantly share code, notes, and snippets.

@hkitago
Created July 28, 2023 05:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hkitago/aaa157555bf281faf08417e8b532860d to your computer and use it in GitHub Desktop.
Save hkitago/aaa157555bf281faf08417e8b532860d to your computer and use it in GitHub Desktop.
put SVG file in Canvas
// キャンバスの取得
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// キャンバスを全画面に設定
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// SVGオブジェクトを保持する配列
const svgObjects = [];
// イージング関数
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
}
// SVGファイルを読み込む関数
function loadSVG(url, x, y, width, height) {
const svg = new Image();
svg.src = url;
// タイムスタンプを記録
const timestamp = Date.now();
// アニメーションのフレーム数
const duration = 30000; // 30秒間のアニメーション
const numFrames = 60; // 60フレームで30秒を表現
// 1フレームごとの描画関数
function drawFrame(currentFrame) {
// 時間の進行度合いを0から1の範囲に変換する
const time = currentFrame / numFrames;
// イージング関数を適用して透明度を計算
const opacity = 1 - easeInOutQuad(time);
// キャンバスをクリア
ctx.clearRect(0, 0, canvas.width, canvas.height);
// すべてのSVGオブジェクトを描画
svgObjects.forEach(svgObject => {
ctx.globalAlpha = svgObject.opacity;
ctx.drawImage(svgObject.svg, svgObject.x, svgObject.y, svgObject.width, svgObject.height);
});
// 次のフレームを描画
if (currentFrame < numFrames) {
requestAnimationFrame(() => drawFrame(currentFrame + 1));
} else {
// 30秒後に透過処理アニメーションを開始
const startTime = Date.now() - timestamp;
if (startTime >= 10000 && startTime <= 13000) {
const fadeOutTime = startTime - 10000;
const fadeOutFrames = (fadeOutTime / 3000) * 60; // 3秒間のアニメーション
requestAnimationFrame(() => drawFadeOutFrame(fadeOutFrames, svgObjects.length - 1));
}
}
}
function drawFadeOutFrame(currentFrame, index) {
// 時間の進行度合いを0から1の範囲に変換する
const time = currentFrame / 60;
// イージング関数を適用して透明度を計算
const opacity = 1 - easeInOutQuad(time);
// キャンバスをクリア
ctx.clearRect(0, 0, canvas.width, canvas.height);
// すべてのSVGオブジェクトを描画
svgObjects.forEach((svgObject, i) => {
if (i === index) {
svgObject.opacity = opacity; // 透過処理アニメーションを適用
}
ctx.globalAlpha = svgObject.opacity;
ctx.drawImage(svgObject.svg, svgObject.x, svgObject.y, svgObject.width, svgObject.height);
});
// 次のフレームを描画
if (currentFrame < 60) {
requestAnimationFrame(() => drawFadeOutFrame(currentFrame + 1, index));
} else {
svgObjects.splice(index, 1); // アニメーションが終わったらSVGオブジェクトを配列から削除
ctx.clearRect(0, 0, canvas.width, canvas.height); // キャンバスをクリア
svgObjects.forEach(svgObject => {
ctx.globalAlpha = svgObject.opacity;
ctx.drawImage(svgObject.svg, svgObject.x, svgObject.y, svgObject.width, svgObject.height);
});
}
}
svg.onload = function() {
// アニメーションを開始
requestAnimationFrame(() => drawFrame(0));
};
// SVGオブジェクトを配列に追加
svgObjects.push({ svg, x, y, width, height, opacity: 1 });
}
// タップとクリックの両方に対応した関数
function placeSVGOnTapOrClick(event) {
let tapX, tapY;
if (event.touches && event.touches.length > 0) {
// タッチイベントの場合
tapX = event.touches[0].clientX;
tapY = event.touches[0].clientY;
} else {
// クリックイベントの場合
tapX = event.clientX;
tapY = event.clientY;
}
// SVGの幅と高さ
const svgWidth = 100; // ここにSVGの幅を指定します
const svgHeight = 100; // ここにSVGの高さを指定します
// SVGをタップやクリックの中心に配置するために、表示位置を計算
const svgX = tapX - svgWidth / 2;
const svgY = tapY - svgHeight / 2;
// ここで、SVGファイルのURLと計算した表示位置を指定します。
loadSVG('nanii.svg', svgX, svgY, svgWidth, svgHeight);
}
// タップイベントリスナーを追加
canvas.addEventListener('click', placeSVGOnTapOrClick);
// クリックイベントリスナーを追加(タッチの場合も考慮)
canvas.addEventListener('touchend', placeSVGOnTapOrClick);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment