- エーオーシステム コーポレートサイト
https://www.aosystem.co.jp/ - エーオーシステム プロダクトサイト
https://ao-system.net/ - レンタルサーバー
- バーチャル展示会
- ウェブカタログサービス
- 3Dグラフィック
- Android アプリ
- iOS (iPhone,iPad) アプリ
- Flutter開発
- プログラミング記録QuickAnswer
- 無料画像素材
- スカイボックス 3D SKY BOX
このページのQRコード
Animation first と Animation second の混合になります。まずは Animation first で基本の動作を決めて、Animation second で掛け合わせる動作を決めます。
Animation first -- 1:アニメ無し 2:左から右 3:左上から右下 4:モザイク 5:中央カーテン 6:菱形 7:楕円
Animation second -- 1:アニメ無し 2:上から下 3:左から右
/**
* 画像切り替え canvas版
*
* @author ao-system, Inc.
* @date 2024-01-08
* @date 2024-01-17 Rewrite the code using the class syntax.
*
<section class="switchpanel">
<div>
<div id="switchPanelStage"></div>
</div>
</section>
<style>
section.switchpanel {
background-color: #eee;
> div {
max-width: 1920px;
margin: 0 auto;
overflow: hidden;
> #switchPanelStage {
user-select: none;
display: grid;
grid-template-rows: 1fr;
grid-template-columns: 1fr;
> canvas {
z-index: 0;
grid-row: 1/2;
grid-column: 1/2;
width: 100%;
}
> div {
z-index: 1;
grid-row: 1/2;
grid-column: 1/2;
justify-self: flex-end;
align-self: end;
display: flex;
justify-content: center;
align-items: center;
column-gap: 5px;
padding: 0 20px 20px 0;
@media (width < 670px) {
column-gap: 3px;
padding: 0 3px 3px 0;
> span {
> img {
width: 16px;
}
}
}
> span {
cursor: pointer;
> img:nth-of-type(1) {
display: block;
}
> img:nth-of-type(2) {
display: none;
}
&.on {
> img:nth-of-type(1) {
display: none;
}
> img:nth-of-type(2) {
display: block;
}
}
}
}
}
}
}
</style>
*
*/
(() => {
'use strict';
class SwitchImage {
#constProperties = [
{prop: 'stage', value: document.getElementById('switchPanelStage')},
{prop: 'canvas', value: document.createElement('canvas')},
{prop: 'layerBall', value: document.createElement('div')},
{prop: 'markPause', value: './image/panel_pause.svg'},
{prop: 'markPlay', value: './image/panel_play.svg'},
{prop: 'markNavOn', value: './image/panel_ball_on.svg'},
{prop: 'markNavOff', value: './image/panel_ball_off.svg'},
{prop: 'buttonPause', value: document.createElement('span')},
{prop: 'buttonPlay', value: document.createElement('span')},
{prop: 'imageChangeInterval', value: 5000}, //画像と画像の切り替え間隔
{prop: 'swipeShreshold', value: 50}, //スワイプ判定幅
];
#ctx = null; //canvas context
#loopTimeoutId = null; //自動動作のタイマー
#isBusy = false; //false|true
#pausePlayFlag = true; //falseで停止
#valueIndex = 0; //this.#valuesの添え字
#lastIsLarge = null; //null|true|false
#animationArray = []; //描画のbuffer
#swipeStartX = 0; //スワイプ開始位置
#isSwiping = false; //スワイプ中 true|false
#config = {};
#values = [];
//
animationFirstNumber = 7; //1|2|3|4|5|6|7
animationSecondNumber = 2; //1|2|3
//
constructor(config, values) {
this.#config = config;
this.#values = values;
this.#constProperties.forEach((obj) => Object.defineProperty(this, obj.prop, {value:obj.value, writable:false}));
this.#ctx = this.canvas.getContext('2d');
this.#init();
}
#init() {
this.stage.appendChild(this.canvas);
this.stage.appendChild(this.layerBall);
//this.#values = shuffle(this.#values); //シャッフルさせる場合
this.#setCanvasSize();
this.#initBall();
this.#setImage();
this.#initSwipe();
this.#autoSlide();
}
#shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
#initBall() {
this.#values.map((x,index) => {
const span = document.createElement('span');
span.addEventListener('click',() => {this.#slideNumber(index);});
span.innerHTML = '<img src="' + this.markNavOff + '"><img src="' + this.markNavOn + '">';
this.layerBall.appendChild(span);
});
const pauseImg = new Image();
pauseImg.src = this.markPause;
this.buttonPause.appendChild(pauseImg);
this.layerBall.appendChild(this.buttonPause);
const playImg = new Image();
playImg.src = this.markPlay;
this.buttonPlay.appendChild(playImg);
this.layerBall.appendChild(this.buttonPlay);
this.buttonPlay.style.display = 'none';
this.buttonPause.addEventListener('click',() => this.#setPause());
this.buttonPlay.addEventListener('click',() => this.#setPlay());
}
#initSwipe() {
this.canvas.addEventListener('click', (e) => { e.preventDefault();});
this.canvas.addEventListener('mousedown', (e) => { this.#swipeStart(e.clientX); });
this.canvas.addEventListener('mouseup', (e) => { this.#swipeEnd(e.clientX); });
this.canvas.addEventListener('touchstart', (e) => { this.#swipeStart(e.touches[0].clientX); });
this.canvas.addEventListener('touchend', (e) => { this.#swipeEnd(e.changedTouches[0].clientX); });
}
#swipeStart(positionX) {
if (this.#isBusy) {
return;
}
this.#swipeStartX = positionX;
this.canvas.style.cursor = 'grabbing';
this.#isSwiping = true;
}
#swipeEnd(positionX) {
if (this.#isSwiping == false) {
return;
}
if (this.#swipeStartX - positionX > this.swipeShreshold) {
this.#slideNumber(this.#withinRange(this.#valueIndex + 1));
} else if (this.#swipeStartX - positionX < -this.swipeShreshold) {
this.#slideNumber(this.#withinRange(this.#valueIndex - 1));
} else {
if (this.#values[this.#valueIndex].link) {
if (this.#values[this.#valueIndex].external) {
window.open(this.#values[this.#valueIndex].link, '_blank');
} else {
window.location.href = this.#values[this.#valueIndex].link;
}
return;
}
}
this.canvas.style.cursor = '';
this.#isSwiping = false;
}
#setCanvasSize() {
const isLarge = this.#getIsLarge();
if (this.#lastIsLarge != isLarge) {
this.canvas.width = isLarge ? this.#config.width1 : this.#config.width2;
this.canvas.height = isLarge ? this.#config.height1 : this.#config.height2;
this.#lastIsLarge = isLarge;
}
}
#getIsLarge() {
return window.matchMedia('(width >= ' + this.#config.breakpoint + 'px)').matches;
}
#setImage() {
this.#setCanvasSize();
const img = new Image();
img.addEventListener('load',() => this.#imageAnimation(img));
img.src = this.#getIsLarge() ? this.#values[this.#valueIndex].image1 : this.#values[this.#valueIndex].image2;
this.#setBall();
}
#setBall() {
const spans = this.layerBall.querySelectorAll('span');
spans.forEach((elm) => elm.classList.remove('on'));
spans[this.#valueIndex].classList.add('on');
}
#setPause() {
this.#pausePlayFlag = false;
this.buttonPause.style.display = 'none';
this.buttonPlay.style.display = 'block';
}
#setPlay() {
this.#pausePlayFlag = true;
this.buttonPause.style.display = 'block';
this.buttonPlay.style.display = 'none';
}
#autoSlide() {
this.#loopTimeoutId = setTimeout(() => {
this.#slideAction();
},this.imageChangeInterval);
}
#slideAction() {
if (this.#pausePlayFlag) {
this.#valueIndex = this.#withinRange(this.#valueIndex + 1);
this.#setImage();
}
this.#autoSlide();
}
#slideNumber(num) {
if (this.#isBusy) {
return;
}
clearTimeout(this.#loopTimeoutId);
//setPlay();
this.#valueIndex = num;
this.#setImage();
this.#autoSlide();
}
#withinRange(nextNumber) {
let num = nextNumber;
if (num < 0) {
num = this.#values.length - 1;
}
return num % this.#values.length;
}
//------------------------------
//animationの振り分け後に描画
#imageAnimation(img) {
this.#animationArray = [];
if (this.animationFirstNumber == 1) {
this.#imageAnimationFirst01(img);
} else if (this.animationFirstNumber == 2) {
this.#imageAnimationFirst02(img);
} else if (this.animationFirstNumber == 3) {
this.#imageAnimationFirst03(img);
} else if (this.animationFirstNumber == 4) {
this.#imageAnimationFirst04(img);
} else if (this.animationFirstNumber == 5) {
this.#imageAnimationFirst05(img);
} else if (this.animationFirstNumber == 6) {
this.#imageAnimationFirst06(img);
} else if (this.animationFirstNumber == 7) {
this.#imageAnimationFirst07(img);
}
this.#ctxDrawImage(img);
}
//同じdelayの描画はまとめて処理する
#ctxDrawImage(img) {
this.#animationArray.sort((a,b) => {
return a.delay - b.delay;
});
let ary = [];
let lastDelay = -1;
for (let i = 0; i < this.#animationArray.length; i++) {
if (lastDelay != this.#animationArray[i].delay) {
if (ary.length > 0) {
const clonedAry = [...ary];
setTimeout(() => {
clonedAry.forEach((obj) => {
this.#ctx.drawImage(img, obj.srcX, obj.srcY, obj.srcW, obj.srcH, obj.dstX, obj.dstY, obj.dstW, obj.dstH);
});
},clonedAry[0].delay);
}
lastDelay = this.#animationArray[i].delay;
ary = [];
}
ary.push(this.#animationArray[i]);
}
if (ary.length > 0) {
setTimeout(() => {
ary.forEach((obj) => {
this.#ctx.drawImage(img, obj.srcX, obj.srcY, obj.srcW, obj.srcH, obj.dstX, obj.dstY, obj.dstW, obj.dstH);
});
},ary[0].delay);
}
}
//------------------------------
//first animation | no animation
#imageAnimationFirst01(img) {
const delay = 0;
this.#imageAnimationSecond(delay, img, 0, 0, img.width, img.height, 0, 0, this.canvas.width, this.canvas.height);
}
//first animation | left to right
#imageAnimationFirst02(img) {
const divX = 20;
const delayRatio = 25;
const srcW = img.width / divX;
const srcH = img.height;
const dstW = this.canvas.width / divX;
const dstH = this.canvas.height;
const srcY = 0;
const dstY = 0;
for (let x = 0; x < divX; x++) {
const srcX = srcW * x;
const dstX = dstW * x;
const delay = delayRatio * x;
this.#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
}
}
//first animation | left top to right bottom
#imageAnimationFirst03(img) {
const divX = 10;
const divY = 10;
const delayRatio = 10;
const srcW = img.width / divX;
const srcH = img.height / divY;
const dstW = this.canvas.width / divX;
const dstH = this.canvas.height / divY;
for (let y = 0; y < divY; y++) {
for (let x = 0; x < divX; x++) {
const srcX = srcW * x;
const srcY = srcH * y;
const dstX = dstW * x;
const dstY = dstH * y;
const delay = delayRatio * y * x;
this.#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
}
}
}
//first animation | mosaic
#imageAnimationFirst04(img) {
const divX = 40;
const divY = 40;
const delayRatio = 0.4;
const originalArray = Array.from({length: divX * divY}, (_, index) => index);
const shuffledArray = this.#shuffle(originalArray);
const srcW = img.width / divX;
const srcH = img.height / divY;
const dstW = this.canvas.width / divX;
const dstH = this.canvas.height / divY;
let c = 0;
for (let y = 0; y < divY; y++) {
for (let x = 0; x < divX; x++) {
const srcX = srcW * x;
const srcY = srcH * y;
const dstX = dstW * x;
const dstY = dstH * y;
const delay = delayRatio * shuffledArray[c];
this.#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
c += 1;
}
}
}
//first animation | center curtain
#imageAnimationFirst05(img) {
const divX = 40;
const divY = 40;
const delayRatio = 1;
const srcW = img.width / divX;
const srcH = img.height / divY;
const dstW = this.canvas.width / divX;
const dstH = this.canvas.height / divY;
for (let y = 0; y < divY; y++) {
for (let x = 0; x < divX; x++) {
const srcX = srcW * x;
const srcY = srcH * y;
const dstX = dstW * x;
const dstY = dstH * y;
const delay = delayRatio * (Math.abs(y - (divY / 2)) * Math.abs(x - (divX / 2)));
this.#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
}
}
}
//first animation | center rhombus
#imageAnimationFirst06(img) {
const divX = 40;
const divY = 40;
const delayRatio = 15;
const srcW = img.width / divX;
const srcH = img.height / divY;
const dstW = this.canvas.width / divX;
const dstH = this.canvas.height / divY;
for (let y = 0; y < divY; y++) {
for (let x = 0; x < divX; x++) {
const srcX = srcW * x;
const srcY = srcH * y;
const dstX = dstW * x;
const dstY = dstH * y;
const delay = delayRatio * (Math.abs(y - (divY / 2)) + Math.abs(x - (divX / 2)));
this.#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
}
}
}
//first animation | center ellipse
#imageAnimationFirst07(img) {
const divX = 20;
const divY = 20;
const delayRatio = 50;
const srcW = img.width / divX;
const srcH = img.height / divY;
const dstW = this.canvas.width / divX;
const dstH = this.canvas.height / divY;
for (let y = 0; y < divY; y++) {
for (let x = 0; x < divX; x++) {
const srcX = srcW * x;
const srcY = srcH * y;
const dstX = dstW * x;
const dstY = dstH * y;
const delay = delayRatio * Math.sqrt(Math.abs(y - (divY / 2)) ** 2 + Math.abs(x - (divX / 2)) ** 2);
this.#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
}
}
}
//------------------------------
//second animation
#imageAnimationSecond(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH) {
if (this.animationSecondNumber == 1) {
this.#imageAnimationSecond01(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
} else if (this.animationSecondNumber == 2) {
this.#imageAnimationSecond02(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
} else if (this.animationSecondNumber == 3) {
this.#imageAnimationSecond03(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH);
}
}
//second animation | no animation
#imageAnimationSecond01(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH) {
const delay2 = delay;
this.#imageAnimationPush(delay2, img, srcX, srcY, srcW + 1, srcH + 1, dstX, dstY, dstW + 1, dstH + 1);
}
//second animation | top to bottom
#imageAnimationSecond02(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH) {
const divY = 6;
const delayRatio = 60;
const srcH2 = srcH / divY;
const dstH2 = dstH / divY;
for (let y = 0; y < divY; y++) {
const srcY2 = srcY + (srcH2 * y);
const dstY2 = dstY + (dstH2 * y);
const delay2 = delay + (delayRatio * y);
this.#imageAnimationPush(delay2, img, srcX, srcY2, srcW + 1, srcH2 + 1, dstX, dstY2, dstW + 1, dstH2 + 1);
}
}
//second animation | left to right
#imageAnimationSecond03(delay, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH) {
const divX = 6;
const delayRatio = 60;
const srcW2 = srcW / divX;
const dstW2 = dstW / divX;
for (let x = 0; x < divX; x++) {
const srcX2 = srcX + (srcW2 * x);
const dstX2 = dstX + (dstW2 * x);
const delay2 = delay + (delayRatio * x);
this.#imageAnimationPush(delay2, img, srcX2, srcY, srcW2 + 1, srcH + 1, dstX2, dstY, dstW2 + 1, dstH + 1);
}
}
//------------------------------
//画像描画を配列に収める
#imageAnimationPush(delay2, img, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH) {
const delay3 = parseInt(delay2);
this.#animationArray.push({
'delay': delay3,
//'img': img,
'srcX': srcX,
'srcY': srcY,
'srcW': srcW,
'srcH': srcH,
'dstX': dstX,
'dstY': dstY,
'dstW': dstW,
'dstH': dstH,
});
}
}
//
const switchImage = new SwitchImage(
//config
{
'breakpoint': 700,
'width1': 1920,
'height1': 700,
'width2': 700,
'height2': 1000,
},
//values
[
{
'link': '',
'external': false,
'image1': './image/panel01.webp',
'image2': './image/panel01b.webp',
},
{
'link': '',
'external': false,
'image1': './image/panel02.webp',
'image2': './image/panel02b.webp',
},
{
'link': '',
'external': false,
'image1': './image/panel03.webp',
'image2': './image/panel03b.webp',
},
{
'link': '',
'external': false,
'image1': './image/panel04.webp',
'image2': './image/panel04b.webp',
},
{
'link': '',
'external': false,
'image1': './image/panel05.webp',
'image2': './image/panel05b.webp',
},
{
'link': '',
'external': false,
'image1': './image/panel06.webp',
'image2': './image/panel06b.webp',
},
]
);
//暫定機能ここから
document.getElementById('animationFirst').addEventListener('input',(e) => {
const val = e.target.value;
switchImage.animationFirstNumber = val;
document.getElementById('animationFirstValue').innerHTML = val;
});
document.getElementById('animationFirstValue').innerHTML = document.getElementById('animationFirst').value;
document.getElementById('animationSecond').addEventListener('input',(e) => {
const val = e.target.value;
switchImage.animationSecondNumber = val;
document.getElementById('animationSecondValue').innerHTML = val;
});
document.getElementById('animationSecondValue').innerHTML = document.getElementById('animationSecond').value;
//暫定機能ここまで
})();
このページのQRコード
便利ウェブサイト
便利 Android アプリ
便利 iOS(iPhone,iPad) アプリ