Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
css
body { background: #262626; } #c { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
JavaScript
// These have to be ordered by size (ascending) for them to be correctly drawn var circles = [ { color: '#21a5ad', size: 84, angle: Math.PI / 3 }, { color: '#ffad10', size: 92, angle: - Math.PI / 3 }, { color: '#ef4239', size: 100, angle: 0 } ]; // To be able to "twist a circle", it has to be defined as a set of linked points // This is the number of these points (you can see it if you set it to 3 or 4) var segmentsPerCircle = 200; // Time scaling factor : slower when closer to 0, faster when bigger than 1 var speed = .8; // Easing function on the twist (indicates how fast the rotation goes at a given time) // This is equivalent to an ease-in-out-quad // A list of basic easings is available here https://gist.github.com/gre/1650294 function twistEasing(t) { return (t < .5) ? 2 * t * t : 1 - 2 * (t = 1 - t) * t; } var c = document.getElementById('c'), ctx = c.getContext('2d'); Math.PI2 = 2 * Math.PI; // ˉ\_(ツ)_/ˉ // "3d" rotation functions, around base axes // I didn't feel like using matrices so it uses basic 2d geometry and rotation algorithms (trigonometry, pythagore) // rotateZ is a standard 2d rotation around [0,0] (measures the distance, the current angle and increases it, then goes back to X,Y coordinates) // rotateX and rotateY are the same but as if we were viewing the scene from above (for rotateY, so y becomes z) or from the right function rotateX(p, a) { var d = Math.sqrt(p[2] * p[2] + p[1] * p[1]), na = Math.atan2(p[1], p[2]) + a; return [p[0], d * Math.sin(na), d * Math.cos(na)]; } function rotateY(p, a) { var d = Math.sqrt(p[2] * p[2] + p[0] * p[0]), na = Math.atan2(p[2], p[0]) + a; return [d * Math.cos(na), p[1], d * Math.sin(na)]; } function rotateZ(p, a) { var d = Math.sqrt(p[1] * p[1] + p[0] * p[0]), na = Math.atan2(p[1], p[0]) + a; return [d * Math.cos(na), d * Math.sin(na), p[2]]; } // Change the canvas size and restore other properties (lost when we resize) function resize() { c.width = c.offsetWidth; c.height = c.offsetHeight; ctx.translate(c.width *.5, c.height * .5); ctx.lineWidth = 5; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; } window.addEventListener('resize', resize); resize(); // Variables enabling mouse control (just adds an extra rotation around Y based on the mouse positions) // To get a nicer result we smoothly transition to the new mouse position, so we have to use 2 variables // (one for the actual angle and one for the final one, where the mouse points) var angleOffset = 0, angleOffsetGoal = 0; c.addEventListener('mousemove', function(e) { angleOffsetGoal = Math.PI2 * (e.clientX / c.width - .5); }); c.addEventListener('mouseout', function(e) { angleOffsetGoal = 0; }); // This is one of the main elements I guess, it creates a regular polygon (so something close to a circle with enough points) // but also rotates the points around the X axis progressively from 0 at the left up to `angle` at the right // this creates the "twist". Here is what it would look like with twelve points and different `angle` values https://imgur.com/a/5FmOn function loxo(radius, angle, segments) { var r = []; for(var i = 0; i < segments; i++) { // We place the points regularly on a full circle so the angle increment is 2*PI (radians so 1 turn) divided by the number of segments // (and we multiply that by i to get the current one) var a = Math.PI2 * i / segments, c = Math.cos(a), s = Math.sin(a); var ax = Math.PI * .5; // c is the cosine, which is also the x position of the point on the circle with this angle // in [-1, 1], so (c + 1) * .5 gives the horizontal position from 0 (left) to 1 (right) // And the quantity of rotation around the X axis is basically `angle` multiplied by this 0 to 1 factor ax -= (c + 1) * .5 * angle; // Add the computed point to the list r.push([radius * c, radius * s * Math.sin(ax), radius * s * Math.cos(ax)]); } return r; } // The computing and drawing loop, calling itself with requestAnimationFrame // (basically runs 60 times per second when possible) function loop() { requestAnimationFrame(loop); // We move the mouse rotation towards its goal // (this formula makes it decelerate at the end, because it's always going 10% closer than what it was at the previous frame ; this gives a smooth transition) angleOffset += (angleOffsetGoal - angleOffset) * .1; ctx.clearRect(-c.width*.5,-c.height*.5,c.width,c.height); // We get a number between 0 and PI based on the current time indicating the progress of the animation var t = (Date.now() * 1e-3 * speed) % Math.PI; // global rotation : the assembly does half of a turn around Y (if you look at the extremity starting facing us, it ends up on the back) // (it's actually offseted by PI/2 because the loxo function gives circles facing us and we want to start the animation looking at the side) var rotationY = -t - Math.PI * .5; // You can also see the extremity do this up and down and then back to the middle thing, which is basically a sine wave // It can be seen in multiple ways but I chose to do a rotateZ after the first Y rotation // You can try setting this variable to 0 to see what it does (it's like 2d-rotating the result) var rotationZ = Math.PI * .5 * Math.cos(t); // The "twist" quantity is how much between 0 and 1 the circles should be var twist = twistEasing((Math.cos(t * 2 + Math.PI) + 1) * .5), twistAngle = twist * 2 * Math.PI2, // and we multiply that by the max angle (2 full turns) to get the `angle` we must send to the loxo function twistSign = (t * 2 > Math.PI ? 1 : -1); var circlesPoints = []; var i, l, j; for(i = 0, l = circles.length; i < l; i++) { var pts = loxo(circles[i].size, twistAngle, segmentsPerCircle); for(j = 0; j < segmentsPerCircle; j++) { // Just rotates the circle by their own angle (as defined at the very top) but moves them together when they are twisted // You can comment this next line to see what it looks like without it pts[j] = rotateX(pts[j], circles[i].angle * (1 - twist) * twistSign); // And apply every other rotation as computed earlier (global Y and Z, and the mouse rotation) // (you should read this chain starting by the innermost function call btw, assuming you consider the XYZ axes don't move with the transformation) // (if you consider the axes to be moving and not absolute, you can read from left to right) // (this is basically the same difference as when you read CSS transformations, cf this post https://codepen.io/bali_balo/post/chaining-transforms) pts[j] = rotateY(rotateZ(rotateY(pts[j], rotationY), rotationZ), angleOffset); } // Put the result in an array of arrays (array of circles and each circle is an array of points) circlesPoints.push(pts); } // Draw the result in two steps to get a correct z-ordering // First we draw everything that is "behind" the middle (that should be further from you than the center of the sphere) // going from the biggest circle (farther lines) to the smallest drawCircles(circlesPoints, true); // Then we draw the other half (closer to you) // this time drawing the smaller circles first (because on this half they are farther away) drawCircles(circlesPoints, false); } // Function that draws one half of all the circles (called twice to draw the full thing) function drawCircles(circlesPoints, behind) { var i, l = circles.length; // Connects the dots basically for(var i = behind ? l - 1 : 0; i >= 0 && i < l; behind ? i-- : i++) { ctx.strokeStyle = circles[i].color; ctx.beginPath(); for(var j = 0; j < segmentsPerCircle; j++) { var p = circlesPoints[i][j]; // Gets rid of the points on the wrong half if(behind ? p[2] < 0 : p[2] > 0) continue; var prev = circlesPoints[i][(j || segmentsPerCircle) - 1]; ctx.moveTo(prev[0], prev[1]); ctx.lineTo(p[0], p[1]); } ctx.stroke(); } } // Starts the thing ! requestAnimationFrame(loop);
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>canvas 盘绕线-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号