<!--
Colorful Painting
-->
<!-- using three.js -->
<!-- Stanford bunny http://graphics.stanford.edu/data/3Dscanrep/ -->
<div id="container"></div>
<p id="msg_start">Click me🐰</p>
<div class="color-selector">
<input type="radio" id="random" name="colors" checked />
<label for="random" title="Random Color" /></label>
<input type="radio" id="selectcolor" name="colors" />
<label for="selectcolor" title="Color Select" /><input type="color" id="colorpicker" name="colorpicker" /></label>
<input type="radio" id="clear" name="colors" />
<label for="clear" title="Clear" /></label>
<script async src="https://ga.jspm.io/npm:es-module-shims@1.6.3/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.150.1/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.150.1/examples/jsm/"
}
}
</script>
@import url("https://fonts.googleapis.com/css2?family=Asap&display=swap");
* {
margin: 0;
padding: 0;
}
body {
font-family: "Asap", sans-serif;
position: relative;
width: 100vw;
height: 100vh;
text-align: center;
background: radial-gradient(circle, #82707a, #24111e 100%);
}
p {
color: white;
position: fixed;
font-size: 8vh;
bottom: 5px;
left: 0;
right: 0;
pointer-events: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
z-index: 2;
}
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
padding: 0;
z-index: 1;
}
.color-selector {
display: flex;
flex-direction: column;
position: absolute;
right: 0;
top: 0;
margin: 0.2em;
z-index: 2;
}
[type="radio"] {
display: none;
}
[type="radio"]:checked + label:before {
box-shadow: 0px 0px 0px 2px #f9f9f9, 0 0 0 4px #cacaca;
}
label {
position: relative;
display: inline-flex;
align-items: center;
margin: 0.7em 0px;
padding: 0;
cursor: pointer;
font-size: 0.7em;
}
label:before {
display: inline-block;
content: "";
background: var(--c-bg);
width: 2.5em;
height: 2.5em;
border-radius: 50%;
margin-right: 0.3em;
}
label[for="selectcolor"] {
--c-bg: var(--selectcolor);
}
label[for="random"] {
--c-bg: var(--random);
}
label[for="clear"] {
--c-bg: var(--clear);
}
input[type="color"] {
width: 2.5em;
height: 2.5em;
border: none;
opacity: 0;
}
label[for="selectcolor"]:after {
position: absolute;
bottom: 0.4em;
right: 0.1em;
content: "";
width: 2em;
height: 2em;
pointer-events: none;
background-size: contain;
background-repeat: no-repeat;
background-image: url(https://happy358.github.io/Images/Icon/color_circle.png);
}
function e(e, t) {
if (void 0 !== f)
if (
((y.x = (e / window.innerWidth) * 2 - 1),
(y.y = (-t / window.innerHeight) * 2 + 1),
w.setFromCamera(y, d),
w.intersectObject(f, !1, H),
H.length > 0)
) {
const e = H[0].point;
h.point.copy(e), b.position.copy(e);
const t = H[0].face.normal.clone();
t.transformDirection(f.matrixWorld),
t.multiplyScalar(10),
t.add(H[0].point),
h.normal.copy(H[0].face.normal),
b.lookAt(t);
const n = E.geometry.attributes.position;
n.setXYZ(0, e.x, e.y, e.z),
n.setXYZ(1, t.x, t.y, t.z),
(n.needsUpdate = !0),
(h.intersects = !0),
(H.length = 0);
} else h.intersects = !1;
}
function t() {
window.addEventListener(
"pointerdown",
function () {
document.getElementById("msg_start").style.display = "none";
},
{
once: !0
}
),
x.copy(h.point),
L.copy(b.rotation),
k.rotate && (L.z = 2 * Math.random() * Math.PI);
const e = k.minScale + Math.random() * (k.maxScale - k.minScale);
v.set(e, e, e);
const t = S.clone();
"random" == p
? t.color.setHSL(
Math.abs(THREE.MathUtils.randInt(0, 1e3) / 1e3),
1,
THREE.MathUtils.randInt(550, 700) / 1e3
)
: t.color.set(p);
const n = new THREE.Mesh(new c(f, x, L, v), t);
M.push(n), l.add(n), (h.intersects = !0);
}
function n() {
M.forEach(function (e) {
l.remove(e);
}),
(M.length = 0);
}
function o() {
(d.aspect = window.innerWidth / window.innerHeight),
d.updateProjectionMatrix(),
s.setSize(window.innerWidth, window.innerHeight);
}
import * as THREE from "three";
import { OrbitControls as r } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader as i } from "three/addons/loaders/GLTFLoader.js";
import { DecalGeometry as c } from "three/addons/geometries/DecalGeometry.js";
const a = document.getElementById("container");
let s,
l,
d,
m,
f,
w,
E,
u,
p = "random";
const h = {
intersects: !1,
point: new THREE.Vector3(),
normal: new THREE.Vector3()
},
y = new THREE.Vector2(),
H = [],
g = new THREE.TextureLoader(),
R = g.load("https://threejs.org/examples/textures/decal/decal-diffuse.png"),
T = g.load("https://threejs.org/examples/textures/decal/decal-normal.jpg"),
S = new THREE.MeshPhongMaterial({
specular: 4473924,
map: R,
normalMap: T,
normalScale: new THREE.Vector2(1, 1),
shininess: 30,
transparent: !0,
depthTest: !0,
depthWrite: !1,
polygonOffset: !0,
polygonOffsetFactor: -4,
wireframe: !1
}),
M = [];
let b;
const x = new THREE.Vector3(),
L = new THREE.Euler(),
v = new THREE.Vector3(10, 10, 10),
k = {
minScale: 10,
maxScale: 20,
rotate: !0,
clear: function () {
n();
}
};
!(function () {
(s = new THREE.WebGLRenderer({
antialias: !0,
alpha: !0
})).setPixelRatio(window.devicePixelRatio),
s.setSize(window.innerWidth, window.innerHeight),
a.appendChild(s.domElement),
(l = new THREE.Scene()),
((d = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
1e3
)).position.y = 50),
(d.position.z = 120),
((m = new r(d, s.domElement)).minDistance = 50),
(m.maxDistance = 200),
(m.enableDamping = !0),
(m.enablePan = !1),
l.add(new THREE.AmbientLight(4469555));
const n = new THREE.DirectionalLight(16768460, 0.8);
n.position.set(10, 10, 30), l.add(n);
const c = new THREE.DirectionalLight(13421823, 0.8);
c.position.set(-10, 10, -30), l.add(c);
const p = new THREE.BufferGeometry();
p.setFromPoints([new THREE.Vector3(), new THREE.Vector3()]),
(E = new THREE.Line(p, new THREE.LineBasicMaterial())),
((u = new i()).crossOrigin = ""),
u.setPath("https://happy358.github.io/Images/Model/"),
u.load("Bunny.glb", function (n) {
((f = n.scene.children[0]).material = new THREE.MeshStandardMaterial({
color: "floralwhite",
metalness: 0,
roughness: 1
})),
f.scale.set(38, 38, 38),
l.add(f),
setTimeout(() => {
e(window.innerWidth / 2, window.innerHeight / 2),
t(),
e((window.innerWidth / 2) * 1.15, (window.innerHeight / 2) * 1.2),
t();
}, 1e3);
}),
(w = new THREE.Raycaster()),
((b = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 10),
new THREE.MeshNormalMaterial()
)).visible = !1),
l.add(b),
window.addEventListener("resize", o),
window.addEventListener("pointerdown", function (n) {
e(n.clientX, n.clientY), h.intersects && t();
});
})(),
(function e() {
requestAnimationFrame(e), m.update(), s.render(l, d);
})(),
(function () {
"use strict";
function e(e) {
"selectcolor" == e
? (p = document.querySelector("#colorpicker").value)
: "clear" == e
? (window.confirm("Are you sure you want to clear all?") && n(),
(document.querySelector("#random").checked = !0),
(p = "random"))
: (p = e);
}
const t = {
selectcolor: "#ff3399",
random:
"linear-gradient(135deg,#ff7fbf 14%,#ffbf7f 28%,#ffff7f 42%,#bfff7f 56%,#7fffff 70%,#bf7fff 84%,#ff9eff)",
clear: "radial-gradient( #FFF,#FFF , #000)"
};
document.querySelector("#colorpicker").addEventListener("change", (e) => {
let t = e.target.value;
document
.querySelector("label[for='selectcolor']")
.style.setProperty("--selectcolor", t),
(p = t);
}),
document
.querySelector("#colorpicker")
.addEventListener("click", function () {
(document.querySelector("#selectcolor").checked = !0),
(p = document.querySelector("#colorpicker").value);
}),
(function () {
const e = document.querySelector(".color-selector");
Object.keys(t).map((n) => {
e.style.setProperty(`--${n}`, t[n]);
}),
(document.querySelector("#colorpicker").value = t.selectcolor);
})(),
(function () {
let t = document.querySelectorAll("input[type='radio'][name='colors']");
for (let n of t)
n.addEventListener("click", () => {
e(`${n.id}`);
});
})();
})();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.