- エーオーシステム コーポレートサイト
https://www.aosystem.co.jp/ - エーオーシステム プロダクトサイト
https://ao-system.net/ - レンタルサーバー
- バーチャル展示会
- ウェブカタログサービス
- 3Dグラフィック
- Android アプリ
- iOS (iPhone,iPad) アプリ
- Flutter開発
- プログラミング記録QuickAnswer
- 無料画像素材
- スカイボックス 3D SKY BOX
このページのQRコード
/**
* バブルの様なSVG画像出力
*
* @author ao-system, Inc.
* @date 2024-02-04
*/
export class BubbleImage {
'use strict';
#transform = 20;
#points = Array.from({length:8}, () => Math.random() * (this.#transform * 2) - this.#transform);
#offsets = Array.from({length:8}, () => 0.2 + Math.random() * 0.2); //speed
#scaleDirection = 0; //0:なし -1:小さくなる 1:大きくなる
#scale = 1;
#color = ['rgba(255,255,255,0.2)','rgba(150,200,200,0.5)'];
#filter = 'blur(3px) drop-shadow(0 0px 3px rgba(255,255,255,0.5))';
#svgElm;
#svgPath;
#animationId;
constructor(param) {
if (param.color) {
this.#color = param.color;
}
if (param.filter) {
this.#filter = param.filter;
}
this.#init();
}
set color(val) {
this.#color = val;
this.#createSvg();
}
set filter(val) {
this.#filter = val;
this.#createSvg();
}
get svg() {
return this.#svgElm;
}
dispose() {
cancelAnimationFrame(this.#animationId);
const bomb = this.#svgElm.classList.contains('bomb');
this.#svgElm = undefined;
return bomb;
}
#init() {
this.#createSvg();
this.#animateSvg();
}
//<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" height="200px" viewBox="0 0 200 200">
// <radialGradient id="rg" cx="100" cy="100" r="50%" gradientUnits="userSpaceOnUse">
// <stop offset="0" style="stop-color:#7f6"/>
// <stop offset="1" style="stop-color:#ff9"/>
// </radialGradient>
// <path fill="url(#rg)" d="M150,100C150,127,127,150,100,150S50,127,50,100S72,50,100,50S150,72,150,100z"/>
//</svg>
#createSvg() {
const radialGradientId = this.#generateRandomId();
this.#svgElm = document.createElementNS('http://www.w3.org/2000/svg','svg');
this.#svgElm.setAttribute('xmlns','http://www.w3.org/2000/svg');
//this.#svgElm.setAttribute('width','200px');
//this.#svgElm.setAttribute('height','200px');
this.#svgElm.setAttribute('viewBox','0 0 200 200');
this.#svgElm.style.filter = this.#filter;
this.#svgElm.style.transform = 'scale(' + this.#scale + ')';
const radialGradient = document.createElementNS('http://www.w3.org/2000/svg','radialGradient');
radialGradient.setAttribute('id',radialGradientId);
radialGradient.setAttribute('cx',100);
radialGradient.setAttribute('cy',100);
radialGradient.setAttribute('r','50%');
radialGradient.setAttribute('gradientUnits','userSpaceOnUse');
const stop1 = document.createElementNS('http://www.w3.org/2000/svg','stop');
stop1.setAttribute('offset',0);
stop1.setAttribute('style','stop-color:' + this.#color[0]);
const stop2 = document.createElementNS('http://www.w3.org/2000/svg','stop');
stop2.setAttribute('offset',1);
stop2.setAttribute('style','stop-color:' + this.#color[1]);
this.#svgPath = document.createElementNS('http://www.w3.org/2000/svg','path');
this.#svgPath.setAttribute('fill','url(#' + radialGradientId + ')');
radialGradient.appendChild(stop1);
radialGradient.appendChild(stop2);
this.#svgElm.appendChild(radialGradient);
this.#svgElm.appendChild(this.#svgPath);
this.#svgElm.addEventListener('mouseover', () => {
this.#svgElm.classList.add('bomb');
stop1.setAttribute('style','stop-color:' + '#f00');
if (this.#scaleDirection == 0) {
this.#scaleDirection = -1;
}
});
}
#generateRandomId(idLength = 12) {
const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
return Array.from({length:idLength}, () => characters[Math.floor(Math.random() * characters.length)]).join('');
}
#animateSvg() {
if (typeof this.#svgElm == 'undefined') {
return;
}
if (this.#scaleDirection == -1) {
this.#scale -= 0.05;
this.#svgElm.style.transform = 'scale(' + this.#scale + ')';
if (this.#scale < 0.5) {
this.#scaleDirection = 1;
}
} else if (this.#scaleDirection == 1) {
this.#scale += 0.005;
this.#svgElm.style.transform = 'scale(' + this.#scale + ')';
if (this.#scale >= 1) {
this.#scaleDirection = 0;
}
}
//
for (let i = 0; i < this.#points.length; i++) {
this.#points[i] += this.#offsets[i];
if (this.#points[i] > this.#transform || this.#points[i] < -this.#transform) {
this.#offsets[i] *= -1;
}
}
const d = [
`M${150 + this.#points[0]},${100 + this.#points[1]}C${150 + this.#points[0]},${127 + this.#points[1]},${127 + this.#points[2]},${150 + this.#points[3]},${100 + this.#points[2]},${150 + this.#points[3]}`,
`S${50 + this.#points[4]},${127 + this.#points[5]},${50 + this.#points[4]},${100 + this.#points[5]}`,
`S${72 + this.#points[6]},${50 + this.#points[7]},${100 + this.#points[6]},${50 + this.#points[7]}`,
`S${150 + this.#points[0]},${72 + this.#points[1]},${150 + this.#points[0]},${100 + this.#points[1]}`,
`z`,
].join('');
this.#svgPath.setAttribute('d',d);
this.#animationId = requestAnimationFrame(() => this.#animateSvg());
}
}
このページのQRコード
便利ウェブサイト
便利 Android アプリ
便利 iOS(iPhone,iPad) アプリ