通过JavaScript实现动态圣诞树详解
作者:海拥✘
这篇文章主要为大家介绍几个好看的基于HTML+CSS+JS的圣诞树,希望圣诞节那天圣诞老爷爷能把我喜欢的你塞到我床上。感兴趣的小伙伴可以跟随小编一起学习一下
一、只使用 CSS 制作的动画圣诞树
演示地址:http://haiyong.site/christmastree1(建议使用电脑打开,没做响应式手机端会有些变形,或者可以看看后面的圣诞树)
HTML代码:
这里的HTML代码是完整无删减的
<div class="card-container"> <div class="snow-flakes-1"></div> <div class="snow-flakes-2"></div> <h2>接下来是雪花,圣诞树,新年和</h2> <h1>更好的我们</h1> <div class="tree-container"> <div class="ball-0"></div> <div class="tree-p1"> <ul> <li> <div class="xmas-ball ball-1"></div> <div class="tree-left-branch"></div> </li> <li><div class="tree-right-branch"></div></li> </ul> </div> <div class="tree-p2"> <ul> <li> <div class="xmas-ball ball-2"></div> <div class="tree-left-branch"></div> </li> <li> <div class="xmas-ball ball-3"></div> <div class="tree-right-branch"></div> </li> </ul> </div> <div class="tree-p3"> <ul> <li> <div class="xmas-ball ball-6"></div> <div class="tree-left-branch"></div> </li> <li> <div class="xmas-ball ball-5"></div> <div class="xmas-ball ball-4"></div> <div class="tree-right-branch"></div> </li> </ul> </div> <div class="tree-p4"> <ul> <li> <div class="xmas-ball ball-7"></div> <div class="xmas-ball ball-8"></div> <div class="tree-left-branch"></div> </li> <li> <div class="xmas-ball ball-9"></div> <div class="xmas-ball ball-10"></div> <div class="tree-right-branch stubborn"></div> </li> </ul> </div> <div class="wood"></div> <div class="presents"> <div class="present-container-1"> <div class="tie"></div> <div class="lid"></div> <div class="box"></div> </div> <div class="present-container-2"> <div class="tie"></div> <div class="lid"></div> <div class="box"></div> </div> </div> </div> <h3>圣诞节快乐!</h3> <p><span>from haiyong</span></p> </div>
CSS主要代码
CSS比较多,我截取了部分主要代码
body { height: 100vh; display: flex; justify-content: center; align-items: center; color: #000; } ul { list-style-type: none; } ul li { display: inline-block; } h1 { font-family: "Mountains of Christmas", cursive; font-size: 42px; line-height: 60px; -webkit-background-clip: text; -webkit-text-fill-color: transparent; } h1::before, h1::after { content: "❆"; margin: 0 10px; } h2 { font-family: "Source Sans Pro", sans-serif; font-size: 14px; text-transform: uppercase; letter-spacing: 2px; } h3 { font-family: "Open Sans Condensed", sans-serif; font-weight: 300; font-size: 18px; letter-spacing: 2px; margin-bottom: 5px; } p { font-family: "Dancing Script", cursive; font-size: 20px; font-weight: 700; } span { font-family: "Roboto", sans-serif; font-size: 14px; font-weight: 400; } .card-container { height: 675px; width: 675px; padding: 30px; background-color: rgba(255, 255, 255, 0.6); border: 8px double #fff; border-radius: 20px; text-align: center; border-radius: 50%; -webkit-border-radius: 50%; overflow: hidden; position: relative; -webkit-mask-image: -webkit-radial-gradient(white, black); }
二、只使用 CSS 制作的螺旋圣诞树
演示地址:http://haiyong.site/christmastree2(在手机端和PC端都可以完美响应)
HTML代码
<div class="tree"> <div class="tree__light" style="--appear: 0; --y: 0; --rotate: 1440; --radius: 12.5; --speed: 9.235939340131775; --delay: -2.416794939166802;"></div> <div class="tree__light" style="--appear: 1; --y: 2; --rotate: 1411.2; --radius: 12.25; --speed: 7.165430171444827; --delay: -2.992603509592233;"></div> <div class="tree__light" style="--appear: 2; --y: 4; --rotate: 1382.4; --radius: 12; --speed: 3.5061879558149545; --delay: -0.7704234444726743;"></div> <div class="tree__light" style="--appear: 3; --y: 6; --rotate: 1353.6000000000001; --radius: 11.75; --speed: 4.727223159267884; --delay: -9.55238654379912;"></div> <div class="tree__light" style="--appear: 4; --y: 8; --rotate: 1324.8; --radius: 11.5; --speed: 0.702989829906826; --delay: -4.2545348853934435;"></div> <div class="tree__light" style="--appear: 5; --y: 10; --rotate: 1296; --radius: 11.25; --speed: 6.842573668088441; --delay: -4.560144802030952;"></div> <div class="tree__light" style="--appear: 6; --y: 12; --rotate: 1267.2; --radius: 11; --speed: 5.8193198565131965; --delay: -8.605875056439737;"></div> <!-- 一样的规律一直写到 style="--appear: 49;此处省略为了博客简洁--> <div class="tree__light" style="--appear: 49; --y: 98; --rotate: 28.8; --radius: 0.25; --speed: 1.7070837859932286; --delay: -3.8515175108122546;"></div> <svg class="tree__star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 113.32 108.44" style="--delay: 50"> <path d="M90.19 104.33L57.12 87.38 24.4 105l5.91-36.69L3.44 42.65l36.72-5.72 16.1-33.5L73.06 36.6l36.83 4.97-26.35 26.21z" fill="none" stroke-width="6.88" stroke-linecap="round" stroke-linejoin="round"></path> </svg> </div>
完整CSS代码
复制粘贴即可
* { box-sizing: border-box; } body { background: #233343; min-height: 100vh; display: flex; align-items: center; justify-content: center; perspective: 1200px; transform-style: preserve-3d; } .tree { position: relative; height: 50vmin; width: 25vmin; transform-style: preserve-3d; -webkit-animation: spin 2s infinite linear; animation: spin 2s infinite linear; } .tree__light { transform-style: preserve-3d; position: absolute; height: 1vmin; width: 1vmin; border-radius: 50%; -webkit-animation: flash calc(var(--speed) * 1s) calc(var(--delay) * 1s) infinite steps(4), appear 0.5s calc(var(--appear) * 0.05s) both; animation: flash calc(var(--speed) * 1s) calc(var(--delay) * 1s) infinite steps(4), appear 0.5s calc(var(--appear) * 0.05s) both; left: 50%; transform: translate(-50%, 50%) rotateY(calc(var(--rotate, 0) * 1deg)) translate3d(0, 0, calc(var(--radius, 0) * 1vmin)); bottom: calc(var(--y, 0) * 1%); } .tree__star { stroke-width: 5vmin; stroke: #f5e0a3; filter: drop-shadow(0 0 2vmin #fcf1cf); height: 5vmin; width: 5vmin; overflow: visible !important; bottom: 100%; left: 50%; transform: translate(-50%, 0); position: absolute; stroke-dasharray: 1000 1000; fill: none; -webkit-animation: stroke 1s calc((var(--delay) * 0.95) * 0.05s) both; animation: stroke 1s calc((var(--delay) * 0.95) * 0.05s) both; } @-webkit-keyframes stroke { from { stroke-dashoffset: -1000; } } @keyframes stroke { from { stroke-dashoffset: -1000; } } @-webkit-keyframes spin { to { transform: rotateY(360deg); } } @keyframes spin { to { transform: rotateY(360deg); } } @-webkit-keyframes appear { from { opacity: 0; } } @keyframes appear { from { opacity: 0; } } @-webkit-keyframes flash { 0%, 100% { background: #f00; } 20% { background: #fff; } 40% { background: #f00; } 60% { background: #fff; } 80% { background: #f00; } } @keyframes flash { 0%, 100% { background: #f00; } 20% { background: #fff; } 40% { background: #f00; } 60% { background: #fff; } 80% { background: #f00; } }
三、使用HTML+CSS+JS制作的圣诞树
演示地址:http://haiyong.site/christmastree3(最好在PC端预览)
完整CSS
body { background-color:#151522; overflow: hidden; display: flex; align-items: center; justify-content: center; } body, html { height: 100%; width: 100%; margin: 0; padding: 0; } svg{ width:90%; height:90%; visibility:hidden; }
部分JS
MorphSVGPlugin.convertToPath('polygon'); var xmlns = "http://www.w3.org/2000/svg", xlinkns = "http://www.w3.org/1999/xlink", select = function(s) { return document.querySelector(s); }, selectAll = function(s) { return document.querySelectorAll(s); }, pContainer = select('.pContainer'), mainSVG = select('.mainSVG'), star = select('#star'), sparkle = select('.sparkle'), tree = select('#tree'), showParticle = true, particleColorArray = ['#E8F6F8', '#ACE8F8', '#F6FBFE','#A2CBDC','#B74551', '#5DBA72', '#910B28', '#910B28', '#446D39'], particleTypeArray = ['#star','#circ','#cross','#heart'], particlePool = [], particleCount = 0, numParticles = 201 gsap.set('svg', { visibility: 'visible' }) gsap.set(sparkle, { transformOrigin:'50% 50%', y:-100 }) let getSVGPoints = (path) => { let arr = [] var rawPath = MotionPathPlugin.getRawPath(path)[0]; rawPath.forEach((el, value) => { let obj = {} obj.x = rawPath[value * 2] obj.y = rawPath[(value * 2) + 1] if(value % 2) { arr.push(obj) } }) return arr; } let treePath = getSVGPoints('.treePath') var treeBottomPath = getSVGPoints('.treeBottomPath') var mainTl = gsap.timeline({delay:0, repeat:0}), starTl; function flicker(p){ gsap.killTweensOf(p, {opacity:true}); gsap.fromTo(p, { opacity:1 }, { duration: 0.07, opacity:Math.random(), repeat:-1 }) } function createParticles() { var i = numParticles, p, particleTl, step = numParticles/treePath.length, pos; while (--i > -1) { p = select(particleTypeArray[i%particleTypeArray.length]).cloneNode(true); mainSVG.appendChild(p); p.setAttribute('fill', particleColorArray[i % particleColorArray.length]); p.setAttribute('class', "particle"); particlePool.push(p); gsap.set(p, { x:-100, y:-100, transformOrigin:'50% 50%' }) } } var getScale = gsap.utils.random(0.5, 3, 0.001, true); function playParticle(p){ if(!showParticle){return}; var p = particlePool[particleCount] gsap.set(p, { x: gsap.getProperty('.pContainer', 'x'), y: gsap.getProperty('.pContainer', 'y'), scale:getScale() } ); var tl = gsap.timeline(); tl.to(p, { duration: gsap.utils.random(0.61,6), physics2D: { velocity: gsap.utils.random(-23, 23), angle:gsap.utils.random(-180, 180), gravity:gsap.utils.random(-6, 50) }, scale:0, rotation:gsap.utils.random(-123,360), ease: 'power1', onStart:flicker, onStartParams:[p], //repeat:-1, onRepeat: (p) => { gsap.set(p, { scale:getScale() }) }, onRepeatParams: [p] }); particleCount++; particleCount = (particleCount >=numParticles) ? 0 : particleCount } function drawStar(){ starTl = gsap.timeline({onUpdate:playParticle}) starTl.to('.pContainer, .sparkle', { duration: 6, motionPath :{ path: '.treePath', autoRotate: false }, ease: 'linear' }) .to('.pContainer, .sparkle', { duration: 1, onStart:function(){showParticle = false}, x:treeBottomPath[0].x, y:treeBottomPath[0].y }) .to('.pContainer, .sparkle', { duration: 2, onStart:function(){showParticle = true}, motionPath :{ path: '.treeBottomPath', autoRotate: false }, ease: 'linear' },'-=0') .from('.treeBottomMask', { duration: 2, drawSVG:'0% 0%', stroke:'#FFF', ease:'linear' },'-=2') } createParticles(); drawStar(); //ScrubGSAPTimeline(mainTl) mainTl.from(['.treePathMask','.treePotMask'],{ duration: 6, drawSVG:'0% 0%', stroke:'#FFF', stagger: { each: 6 }, duration: gsap.utils.wrap([6, 1,2]), ease:'linear' }) .from('.treeStar', { duration: 3, //skewY:270, scaleY:0, scaleX:0.15, transformOrigin:'50% 50%', ease: 'elastic(1,0.5)' },'-=4') .to('.sparkle', { duration: 3, opacity:0, ease:"rough({strength: 2, points: 100, template: linear, taper: both, randomize: true, clamp: false})" },'-=0') .to('.treeStarOutline', { duration: 1, opacity:1, ease:"rough({strength: 2, points: 16, template: linear, taper: none, randomize: true, clamp: false})" },'+=1') mainTl.add(starTl, 0) gsap.globalTimeline.timeScale(1.5);
四、只使用 CSS 的流星圣诞树
演示地址:http://haiyong.site/christmastree4(响应式的,手机和PC端都可预览)
HTML代码
<ul> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <ul> <!-- 此处省略256行 <li></li> --> </ul>
CSS代码
:root { --background:#3C3B3D; } body { background: var(--background); } body ul { padding: 0; } body ul li { list-style: none; } body ul:nth-child(1) { position: absolute; top: 20vh; left: 50%; width: 1rem; height: 1rem; border-radius: 100%; transform: translate(-50%, -50%); } body ul:nth-child(1) li { position: absolute; width: 0; height: 0; border-width: 0 0.5rem 1rem 0.5rem; border-style: solid; border-color: transparent; border-bottom-color: #FFCE54; transform-origin: 0.5rem 1rem; } body ul:nth-child(1) li:nth-child(0) { transform: rotate(0deg); } body ul:nth-child(1) li:nth-child(1) { transform: rotate(72deg); } body ul:nth-child(1) li:nth-child(2) { transform: rotate(144deg); } body ul:nth-child(1) li:nth-child(3) { transform: rotate(216deg); } body ul:nth-child(1) li:nth-child(4) { transform: rotate(288deg); } body ul:nth-child(2) li { position: absolute; top: 20vh; left: 50%; width: 0.0625rem; height: 60vh; transform-origin: 50% 0%; } body ul:nth-child(2) li:nth-child(1) { transform: rotate(4.9322004015deg); } body ul:nth-child(2) li:nth-child(1):before, body ul:nth-child(2) li:nth-child(1):after { -webkit-animation-delay: -0.015625s; animation-delay: -0.015625s; } body ul:nth-child(2) li:nth-child(2) { transform: rotate(7.7960629984deg); } body ul:nth-child(2) li:nth-child(2):before, body ul:nth-child(2) li:nth-child(2):after { -webkit-animation-delay: -0.03125s; animation-delay: -0.03125s; } body ul:nth-child(2) li:nth-child(3) { transform: rotate(10.5294548885deg); } body ul:nth-child(2) li:nth-child(3):before, body ul:nth-child(2) li:nth-child(3):after { -webkit-animation-delay: -0.046875s; animation-delay: -0.046875s; } /* ...... */ /* 一样的规律,一直到第256 */ body ul:nth-child(2) li:nth-child(256) { transform: rotate(2deg); } body ul:nth-child(2) li:nth-child(256):before, body ul:nth-child(2) li:nth-child(256):after { -webkit-animation-delay: -4s; animation-delay: -4s; } body ul:nth-child(2) li:before, body ul:nth-child(2) li:after { content: ""; position: absolute; top: 0%; -webkit-animation: fall 4s linear infinite; animation: fall 4s linear infinite; } body ul:nth-child(2) li:before { width: 0.0625rem; height: 3rem; background: linear-gradient(rgba(46, 204, 113, 0), rgba(46, 204, 113, 0.5)); } body ul:nth-child(2) li:after { bottom: 0; transform: translate(-50%, 3rem); width: 0.1875rem; height: 0.1875rem; border-radius: 100%; background: #ffce54; } body ul:nth-child(2) li:nth-child(4n):after { background: #D8334A; } body ul:nth-child(2) li:nth-child(4n+1):after { background: #FFCE54; } body ul:nth-child(2) li:nth-child(4n+2):after { background: #2ECC71; } body ul:nth-child(2) li:nth-child(4n+3):after { background: #5D9CEC; } @-webkit-keyframes fall { 0% { opacity: 0; top: 0%; } 5% { opacity: 0; } 15%, 90% { opacity: 1; } 100% { opacity: 0; top: 100%; } } @keyframes fall { 0% { opacity: 0; top: 0%; } 5% { opacity: 0; } 15%, 90% { opacity: 1; } 100% { opacity: 0; top: 100%; } }
五、水晶球里的圣诞树
演示地址:http://haiyong.site/christmastree5(响应式的,手机和PC端都可预览)
CSS完整代码
html, body { margin:0; width: 100%; height: 100%; position: absolute; overflow: hidden; background: linear-gradient(135deg, rgba(180,186,214,1) 0%, rgba(232,203,192,1) 100%); } .content { text-align: center; width: 100%; } svg { max-width: 575px; } #canvas { border-radius: 50%; position: relative; width: 310px; height: 290px; top: 10px; left: 0px; } .canvas_container { position: absolute; width: 100%; } .draw_container { position: absolute; top: 50px; width: 100%; }
JS完整代码
$(function() { var canvas = $("#canvas")[0]; var ctx = canvas.getContext("2d"); var WIDTH = 320; var HEIGHT = 320; canvas.width = WIDTH; canvas.height = HEIGHT; clearCanvas(); var particles = []; for (var i = 0; i < WIDTH; i++) { particles.push({ x: Math.random() * WIDTH, y: Math.random() * HEIGHT, r: Math.random() * 2 + 1 }) } function draw() { clearCanvas(); ctx.fillStyle = "rgba(255, 255, 255, 0.6)"; ctx.beginPath(); for (let i = 0; i < WIDTH; i++) { let p = particles[i]; ctx.moveTo(p.x, p.y); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true); } ctx.fill(); update(); } function update() { for (let i = 0; i < WIDTH; i++) { let p = particles[i]; p.y += p.r; if (p.y > canvas.height) { particles[i] = { x: Math.random() * canvas.width, y: -10, r: p.r }; } } } var timer = setInterval(draw, 50); function clearCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); } })
六、圣诞贺卡
演示地址:http://haiyong.site/shengdanheka
以上就是通过JavaScript实现动态圣诞树详解的详细内容,更多关于JavaScript圣诞树的资料请关注脚本之家其它相关文章!