Смачная Новогодняя ёлочка на HTML5 canvas для вашего сайта
1 2 3 4 |
#treecanvas { background: #000; width:430px; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
<canvas id="treecanvas"></canvas> <script> if (typeof requestAnimationFrame != 'function') { ['moz', 'webkit', 'ms'].some(function (p) { var f = this[p + 'RequestAnimationFrame'] return typeof f == 'function' ? (requestAnimationFrame = f) : false }) || (requestAnimationFrame = function (f) { return setTimeout(f, 0) }) /* jshint -W030 */ } (function (canvas) { /* Settings */ var thetaEnd = 6 * Math.PI, lineSpacing = 1 / 30, lineLength = 0.5 * lineSpacing, rate = 1 / (2 * Math.PI), factor = rate / 3, cycle = 200, scene = [], /* Rendering */ offsetX = 250, offsetY = 300, scaleX = 400, scaleY = 400, camX = 0, camY = 2, camZ = -Math.PI, cSize = 500, c = document.getElementById('treecanvas').getContext('2d') canvas.width = canvas.height = cSize c.lineWidth = 1.44 scene.push(new Coil({ color: '255,0,0', theta0: Math.PI })) scene.push(new Coil({ color: '100,200,255', theta0: Math.PI / 3 })) scene.push(new Coil({ color: '200,255,100', theta0: -Math.PI / 3 })) requestAnimationFrame(paint) function paint() { var offset = 1 - Date.now() / cycle % 1, i = 0 requestAnimationFrame(paint) c.clearRect(0, 0, cSize, cSize) for (; i < scene.length; ++i) scene[i].paint(offset) } function project(point) { return [offsetX + scaleX * (point[0] - camX) / -(point[2] + camZ), offsetY + scaleY * (point[1] - camY) / -(point[2] + camZ)] } function clamp(val, a, b) { return (val < a) ? a : (val > b) ? b : val } function pow3(a) { return a * a * a } function Coil(options) { this.color = options.color || '255,255,255' this.theta0 = options.theta0 || 0 this.lineSpacing = options.lineSpacing || lineSpacing this.lineLength = options.lineLength || lineLength this.rate = options.rate || rate this.factor = options.factor || factor this.cache = {} } Coil.prototype.paint = function (offset) { var cache = this.cache[offset] || (this.cache[offset] = this.compute(offset)) /* Rendering-1 */ cache[0].forEach(function (b) { c.beginPath() c.moveTo(b[0], b[1]) c.lineTo(b[2], b[3]) c.strokeStyle = 'rgba(' + this.color + ',' + b[4] + ')' c.stroke() }, this) /* Rendering-2 */ c.beginPath() cache[1].forEach(function (b) { c.moveTo(b[0], b[1]) c.lineTo(b[2], b[3]) }) c.strokeStyle = 'rgb(' + this.color + ')' c.stroke() } Coil.prototype.compute = function (offset) { var theta = this.thetaDif(0, offset * this.lineSpacing), begin, end, cache0 = [], cache1 = [], i = 0 for (; theta < thetaEnd; theta += this.thetaDif(theta, this.lineSpacing)) { begin = this.getPoint(theta) end = this.getPoint(theta + this.thetaDif(theta, this.lineLength)) this.line(begin, end, cache0, cache1) } return [cache0, cache1] } Coil.prototype.thetaDif = function (theta, length) { return length / Math.sqrt(this.rate * this.rate + this.factor * this.factor * theta * theta) } Coil.prototype.getPoint = function (theta) { return [theta * this.factor * Math.cos(this.theta0 + theta), theta * this.rate, theta * this.factor * Math.sin(this.theta0 + theta)] } Coil.prototype.line = function (begin, end, cache0, cache1) { var opacity = 0.24 + 0.76 * pow3(clamp(0.96 + 5.56 * begin[2], 0, 1)) begin = project(begin) end = project(end) if (opacity == 1) cache1.push([begin[0], begin[1], end[0], end[1]]) else cache0.push([begin[0], begin[1], end[0], end[1], opacity]) } /* Warm up */ scene.forEach(function (obj) { var offset, i = 0 for (; i < 200; ++i) { offset = 1 - i / cycle % 1 obj.cache[offset] = obj.compute(offset) } }) }(document.getElementsByTagName('canvas')[0])) </script> |
По картинке, елка классная! Жаль демо не работает 🙁