该效果预览不是最新的效果图,嫌麻烦把mp4转成gif就不上传新的效果预览了。顺便推荐一下一个在线文件转换格式的网站:https://www.aconvert.com/video/(之前一直在用covertio现在好像收费了)
简述下代码部分吧:(画多棱柱体就不说了,主要讲一下让它支持手势运动)
1.因为在pc端在鼠标按下滑动会产生选中元素的行为,所以在父级元素设置了
user-select:none
2.在旋转的关键帧动画里本来是
form:0deg => to: 360deg
,但是在添加手势事件后的自然旋转会导致旋转速度变快或者变慢(原因是:执行这个自然旋转的动画时间固定为48s,人为去干预了它的旋转角度,导致整个动画的过程缩短或增加,时间却一直都是48s,故如此),baseRotate
为每次重新做手势的基础角度,currentRotate
为每次结束手势产生的旋转角度,然后就想到用css变量来改变关键帧动画的from、to
的角度,body.style.cssText = "--beginDeg:" + currentRotate + "deg;--endDeg:" + (currentRotate + 360) + "deg;";
这样就相当于重置了关键帧动画,这样就保持了动画速度
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
/*n边形的外角和为360 360/n
n变形的内角 180 - 360/n*/
* {
margin: 0;
padding: 0;
}
html,
body {
background-image: radial-gradient(#fff, #000);
height: 100%;
overflow: hidden;
}
#wrap {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
width: 300px;
height: 300px;
/*border: 1px solid;*/
perspective: 1000px;
user-select: none;
}
#wrap>.box {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
width: 300px;
height: 300px;
transition: 10s transform;
transform-style: preserve-3d;
animation-name: rotate;
animation-duration: 48s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
}
#wrap>.box>div {
position: absolute;
width: 300px;
height: 300px;
background: rgba(0, 0, 0, 0.1);
text-align: center;
font: 50px/300px "微软雅黑";
backface-visibility: visible;
}
@keyframes rotate {
form {
transform: rotateY(var(--beginDeg));
}
to {
transform: rotateY(var(--endDeg));
}
}
#wrap:hover>.box {
animation-play-state: paused;
}
</style>
</head>
<body style="--beginDeg:0deg;--endDeg:360deg;">
<div id="wrap">
<div class="box">
</div>
</div>
</body>
<script type="text/javascript">
//n:棱数
window.onload = function () {
createLZ(11);
var down = false;
var startX = 0;
var baseRotate = 0;
var currentRotate = 0;
var wrap = document.getElementById('wrap');
var body = document.body;
var boxNode = document.querySelector("#wrap > .box");
// wrap元素鼠标按下滑动事件
wrap.onmousedown = function (e) {
down = true
startX = e.clientX;
}
wrap.onmousemove = function (e) {
if (down) {
currentRotate = baseRotate + (e.clientX - startX) / 10;
boxNode.style.transform = "rotateY(" + currentRotate + "deg)";
}
}
window.onmouseup = function (e) {
baseRotate = currentRotate;
down = false;
body.style.cssText = "--beginDeg:" + currentRotate + "deg;--endDeg:" + (currentRotate + 360) + "deg;";
}
}
function createLZ(n) {
var boxNode = document.querySelector("#wrap > .box");
var stlyleNode = document.createElement("style");
//外角
var degOut = 360 / n;
//内角
var degIn = 180 - 360 / n;
var text = "";
var cssText = "";
for (var i = 0; i < n; i++) {
text += "<div></div>";
cssText += `#wrap > .box > div:nth-child(${i + 1}){transform: rotateY(${i * degOut}deg);background: url(./img/${i}.jpeg) center no-repeat;}`;
}
boxNode.innerHTML = text;
var mianNode = document.querySelector("#wrap > .box > div");
//棱长
var length = mianNode.offsetWidth;
cssText += "#wrap > .box{transform-origin: center center -" + (length / 2 * Math.tan((degIn / 2) * Math.PI / 180)) + "px;}";
cssText += "#wrap > .box > div{transform-origin: center center -" + (length / 2 * Math.tan((degIn / 2) * Math.PI / 180)) + "px;}";
stlyleNode.innerHTML = cssText;
document.head.appendChild(stlyleNode);
}
</script>
</html>