3D圆形加载器(circle loader)
程序员文章站
2022-04-03 22:47:23
...
示例
HTML
<canvas></canvas>
<!-- twitter / dribbble -->
<a href="https://greensock.com" target="_blank"><img class="gsap-3-logo" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-3-logo.svg"></a>
<a class="dribbble" href="https://dribbble.com/shots/8206266-3D-Circle-Loader" target="_blank"><img src="https://dribbble.com/assets/logo-small-2x-9fe74d2ad7b25fba0f50168523c15fda4c35534f9ea0b1011179275383035439.png" alt=""></a>
<a class="twitter" target="_blank" href="https://twitter.com/aaroniker_me"><svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" viewBox="0 0 72 72"><path d="M67.812 16.141a26.246 26.246 0 0 1-7.519 2.06 13.134 13.134 0 0 0 5.756-7.244 26.127 26.127 0 0 1-8.313 3.176A13.075 13.075 0 0 0 48.182 10c-7.229 0-13.092 5.861-13.092 13.093 0 1.026.118 2.021.338 2.981-10.885-.548-20.528-5.757-26.987-13.679a13.048 13.048 0 0 0-1.771 6.581c0 4.542 2.312 8.551 5.824 10.898a13.048 13.048 0 0 1-5.93-1.638c-.002.055-.002.11-.002.162 0 6.345 4.513 11.638 10.504 12.84a13.177 13.177 0 0 1-3.449.457c-.846 0-1.667-.078-2.465-.231 1.667 5.2 6.499 8.986 12.23 9.09a26.276 26.276 0 0 1-16.26 5.606A26.21 26.21 0 0 1 4 55.976a37.036 37.036 0 0 0 20.067 5.882c24.083 0 37.251-19.949 37.251-37.249 0-.566-.014-1.134-.039-1.694a26.597 26.597 0 0 0 6.533-6.774z"></path></svg></a>
CSS
body {
background: #275EFE;
}
canvas {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
// dribbble & twitter
body {
min-height: 100vh;
overflow: hidden;
.gsap-3-logo {
width: 88px;
position: fixed;
bottom: 12px;
right: 152px;
}
.dribbble {
position: fixed;
display: block;
right: 20px;
bottom: 20px;
img {
display: block;
width: 76px;
}
}
.twitter {
position: fixed;
display: block;
right: 112px;
bottom: 14px;
svg {
width: 24px;
height: 24px;
fill: white;
}
}
}
JS
const $ = (s, o = document) => o.querySelector(s);
let width = 440,
height = 440,
canvas = $('canvas'),
renderer = new THREE.WebGLRenderer({
canvas: canvas,
context: canvas.getContext('webgl2'),
antialias: true,
alpha: true
}),
shape = (inner = 13, outer = 20, height = 6, segments = 60) => {
let arc = new THREE.Shape(),
hole = new THREE.Path();
arc.moveTo(outer, 0);
arc.absarc(0, 0, outer, 0, Math.PI * 2, false);
hole.moveTo(inner, 0);
hole.absarc(0, 0, inner, 0, Math.PI * 2, true);
arc.holes.push(hole);
let geometry = new THREE.ExtrudeGeometry(arc, {
depth: height,
bevelEnabled: false,
curveSegments: segments
}),
material = new THREE.MeshLambertMaterial({
color: 0xD3D4EC
}),
object = new THREE.Mesh(geometry, material),
proxy = new Proxy({
z: null,
s: null
}, {
set(target, key, value) {
target[key] = value;
if(target.z !== null) {
object.position.z = target.z;
}
if(target.s !== null) {
object.scale.x = target.s;
object.scale.y = target.s;
}
return true;
},
get(target, key) {
return target[key];
}
});
object.castShadow = true;
object.receiveShadow = true;
return {
geometry: geometry,
object: object,
proxy: proxy
}
};
renderer.setSize(width, height);
renderer.setPixelRatio(2);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
let scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, width / height, .1, 1000);
camera.position.z = 100;
camera.position.y = -160;
camera.rotation.x = THREE.Math.degToRad(60);
let planeGeometry = new THREE.PlaneGeometry(200, 200),
planeMaterial = new THREE.ShadowMaterial();
planeMaterial.opacity = .1;
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = 6;
plane.receiveShadow = true;
scene.add(plane);
let lightTop = new THREE.DirectionalLight(0xFFFFFF, .4);
lightTop.position.set(100, 100, 200);
lightTop.castShadow = true;
let d = 40;
lightTop.shadow.camera.left = -d;
lightTop.shadow.camera.right = d;
lightTop.shadow.camera.top = d;
lightTop.shadow.camera.bottom = -d;
lightTop.shadow.radius = 8;
scene.add(lightTop);
scene.add(new THREE.AmbientLight(0xE8EBFB));
// Setup
let first = shape(),
second = shape(),
third = shape();
scene.add(first.object);
scene.add(second.object);
scene.add(third.object);
first.proxy.s = .8;
second.proxy.z = 9;
second.proxy.s = .55;
third.proxy.z = 18;
third.proxy.s = .35;
// Animate
gsap.to(first.proxy, {
repeat: -1,
duration: 1,
keyframes: [{
z: 9,
s: .95
}, {
z: 18,
s: .35
}, {
z: 0,
s: .3
}, {
z: 0,
s: .8,
delay: -.1
}]
});
gsap.to(second.proxy, {
repeat: -1,
duration: 1,
keyframes: [{
z: 10,
s: .5
}, {
z: 0,
s: .5
}, {
z: 4,
s: .65
}, {
z: 8,
s: .55
}]
});
gsap.to(third.proxy, {
repeat: -1,
duration: 1,
keyframes: [{
z: 0,
s: .3
}, {
z: 0,
s: .8,
delay: -.1
}, {
z: 9,
s: .95
}, {
z: 18,
s: .35
}]
});
let render = () => {
requestAnimationFrame(render);
renderer.render(scene, camera);
};
render();
更多有趣示例 尽在 小红砖社区https://xhz.bos.xyz
上一篇: 求三角形的面积
推荐阅读
-
springboot的类加载器(org.springframework.boot.loader)过程详解
-
vue-content-loader内容加载器的使用方法
-
webpack中loader加载器配置postCss自动添加CSS兼容前缀
-
Android Studio教程09-加载器Loader的使用
-
springboot的类加载器(org.springframework.boot.loader)过程详解
-
深入解析Java中的Class Loader类加载器
-
飞溅加载器(splash loader)
-
3D圆形加载器(circle loader)
-
深入解析Java中的Class Loader类加载器
-
vue-content-loader内容加载器的使用方法