Slider-frag
デモ
ソースコード
import { Group } from "three";
import { INode, world, config } from "negl";
import { SingleMeshSlider } from "#/parts/helper/slider/SingleMeshSlider";
import vertexShader from "./vertex.glsl";
import fsBefore from "./before.glsl";
import fsAfter from "./after.glsl";
import square from "./square.glsl";
import gate from "./gate.glsl";
import diagonal from "./diagonal.glsl";
import flip from "./flip.glsl";
import book from "./book.glsl";
import collapse from "./collapse.glsl";
import swap from "./swap.glsl";
// パターンを追加する際はこちらに記述
const fragType = {
square,
gate,
diagonal,
flip,
book,
collapse,
swap,
};
// book
const MIN_AMOUNT = -0.16;
const MAX_AMOUNT = 1.5;
export default class extends SingleMeshSlider {
beforeCreateMesh() {
super.beforeCreateMesh();
const type = INode.getDS(this.$.el, "frag") ?? "gate";
this.fragType = type;
this.angleRadian = -Math.PI / 4;
}
setupUniforms() {
const uniforms = super.setupUniforms();
uniforms.progress = uniforms.uProgress;
// book用の処理
if (this.fragType === "book") {
uniforms.amount = {
value: uniforms.progress.value * (MAX_AMOUNT - MIN_AMOUNT) + MIN_AMOUNT,
};
uniforms.cylinderCenter = { value: uniforms.amount.value };
// 360 degrees * uniforms.amount
uniforms.cylinderAngle = { value: 2.0 * Math.PI * uniforms.amount.value };
uniforms.cylinderRadius = { value: 1.0 / Math.PI / 2.0 };
uniforms.progress._value = uniforms.progress.value;
Object.defineProperty(uniforms.progress, "value", {
set: function (newValue) {
this._value = newValue;
uniforms.amount.value =
uniforms.progress.value * (MAX_AMOUNT - MIN_AMOUNT) + MIN_AMOUNT;
uniforms.cylinderCenter.value = uniforms.amount.value;
// 360 degrees * uniforms.amount
uniforms.cylinderAngle.value = 2.0 * Math.PI * uniforms.amount.value;
uniforms.cylinderRadius.value = 1.0 / Math.PI / 2.0;
},
get: function () {
return this._value;
},
});
}
return uniforms;
}
setupVertex() {
return vertexShader;
}
setupFragment() {
const type = INode.getDS(this.$.el, "frag") ?? "gate";
const frag = fragType[type];
this.fragType = type;
const fs = fsBefore + "\n" + frag + "\n" + fsAfter;
return fs;
}
setupMesh() {
const group = new Group();
this.plane = super.setupMesh();
group.add(this.plane);
this.plane.rotation.y = this.angleRadian;
this.plane.position.x += Math.cos(this.angleRadian);
return group;
}
render(tick) {
super.render(tick);
if (this.fragType === "book") {
this.uniforms.amount.value =
this.uniforms.progress.value * (MAX_AMOUNT - MIN_AMOUNT) + MIN_AMOUNT;
}
}
debug(folder) {
super.debug(folder);
folder
.add(this, "angleRadian", -Math.PI, Math.PI, 0.01)
.name("angleRadian")
.listen()
.onChange(() => {
this.plane.rotation.y = this.angleRadian;
});
folder
.add(this, "fragType", [
"square",
"gate",
"diagonal",
"flip",
"book",
"collapse",
"swap",
])
.name("frag")
.onChange(async () => {
const slider = world.getObByEl('[data-webgl="slider-frag"]');
const el = slider.$.el;
el.dataset.frag = this.fragType;
this.fragmentShader = this.setupFragment();
const material = this.setupMaterial();
slider.mesh.children[0].material = material;
});
}
}
利用方法
⚠️
ダウンロードしたコードをプロジェクトに配置し、以下のコードを記述してください。
index.html
<img
class="slider"
data-webgl="slider-frag"
data-frag="book"
data-tex-1="/sample1.jpg"
data-tex-2="/sample2.jpg"
data-tex-3="/sample3.jpg"
data-tex-4="/sample4.jpg"
data-tex-5="/sample5.jpg"
/>
補足
data-frag には下記のいずれかの値を指定してください。デフォルトは"gate"です。
"square", "gate", "diagonal", "flip", "book", "collapse", "swap"
使用画像・動画
- こちらを参考にダウンロードした各ファイルを配置してください。