एचटीएमएल 5 कैनवस पर फ्रैक्टल स्नोफ्लेक्स चलाएं

एचटीएमएल 5 कैनवस पर नए साल की पूर्व संध्या मनोरंजन साइट को स्नोफ्लेक्स के साथ सजाने के लिए (खैर, सिर्फ एक दिलचस्प उदाहरण है कि कैनवस कैसे काम करता है)।



अपनी कहानी में, मैं जियोर्जियो सर्दो कोड का निर्माण करूंगा, जो बदले में डेविड फ्लैनगन कोड पर आधारित है।







नीचे वर्णित सब कुछ, आप सीधे यहां कोशिश कर सकते हैं, किसी भी आधुनिक ब्राउज़र में Habré पर विकास उपकरण के साथ, बस जावास्क्रिप्ट कंसोल को लॉन्च करके। IE9 में, बस F12 दबाएं और यदि आप इस पृष्ठ पर सीधे परीक्षण करना चाहते हैं, तो ब्राउज़र को Internet Explorer 9 मानक (Alt + 9) मोड में रखना न भूलें, जैसा कि डिफ़ॉल्ट रूप से, Habr को IE8 मोड की आवश्यकता होती है।



कैनवास समर्थन की जाँच





सबसे पहले, आपको यह सुनिश्चित करने की आवश्यकता है कि ब्राउज़र कैनवास का समर्थन करता है, इसके लिए आपको कैनवास तत्व बनाने और कार्य के संदर्भ में लाने की कोशिश करनी होगी:



if ( document .createElement( 'canvas' ).getContext) {

...

}

else {

...

}








पहले मामले में, आप आगे बढ़ सकते हैं और बर्फ के टुकड़े शुरू कर सकते हैं।



एक कैनवास बनाएँ





स्नोफ्लेक खींचने के लिए, हम पूर्ण स्क्रीन में एक कैनवास (कैनवास) बनाएंगे:



var canvas = document .createElement( 'canvas' );

canvas.style.position = 'fixed' ;

canvas.style.top = '0px' ;

canvas.style.left = '0px' ;

canvas.style.zIndex = '-10' ;

canvas.width = document .body.offsetWidth;

canvas.height = window.innerHeight;



document .body.insertBefore(canvas, document .body.firstChild);








इस मामले में, हम एक नया कैनवस तत्व बनाते हैं और इसे एक निश्चित स्थान देते हैं, इसे रखने की कोशिश करते हैं ताकि यह बाकी तत्वों के साथ हस्तक्षेप न करे।



अगला हमें प्रतिपादन के लिए संदर्भ मिलता है:



var sky = canvas.getContext( '2d' );







कोच बर्फ का टुकड़ा





मुझे लगता है, हब्रायुज़र्स के लिए, यह अच्छी तरह से जाना जाना चाहिए कि कोच स्नोफ्लेक क्या है , इसलिए मैं खुद को तस्वीर तक सीमित करूंगा:







यह टुकड़ा भग्न है और आसानी से पुनरावर्ती रूप से खींचा गया है। त्रिभुज को खींचने के लिए, आपको उसके प्रत्येक किनारों पर समान ड्राइंग पैटर्न लागू करना होगा:







आइए एक रेखा खींचने की कोशिश शुरू करते हैं। जब प्रतिपादन, जो सुविधाजनक है, हम परिवर्तनों (स्केलिंग और रोटेशन) को लागू कर सकते हैं, जिसमें प्रत्येक स्थानीय प्रतिपादन एक सीधी क्षैतिज रेखा के आरेखण की तरह दिखेगा। यही है, हम लाइन ड्रॉ को घुमाने के बजाय संदर्भ (ट्रांसफॉर्मेशन मैट्रिक्स में बदलाव) को स्केल और घुमाते हैं।



रूपांतरण मैट्रिक्स की स्थिति को बचाने और पुनर्स्थापित करने के लिए, क्रमशः () और पुनर्स्थापना () फ़ंक्शन का उपयोग किया जाता है।



काम के दौरान, हमें डिग्री को रेडियंस में बदलने की आवश्यकता होगी (हालाँकि, यदि आप चाहें, तो आप तुरंत रेडियंस में लिख सकते हैं):



var deg = Math.PI / 180;







एक किनारे खींचने के लिए एक पुनरावर्ती कार्य इस तरह दिखता है:



function leg(n, len) {

sky.save(); //

if (n == 0) { // -

sky.lineTo(len, 0); }

else {

sky.scale(1 / 3, 1 / 3); // 3

leg(n – 1, len); sky.rotate(60 * deg);

leg(n – 1, len); sky.rotate(-120 * deg);

leg(n – 1, len); sky.rotate(60 * deg); leg(n – 1, len); }

sky.restore(); //

sky.translate(len, 0); //

}








रेंडरिंग शुरू करने के लिए, आप निम्न फ़ंक्शन का उपयोग कर सकते हैं:



function drawFlake(x, y, len, n, stroke, fill) {

sky.save(); sky.strokeStyle = stroke;

sky.fillStyle = fill;

sky.beginPath();

sky.translate(x, y);

sky.moveTo(0, 0); leg(n, len); sky.closePath();

sky.fill();

sky.stroke();

sky.restore();

}








ध्यान दें कि आकर्षित करने के लिए, आपको रास्ता बनाना शुरू करना होगा, यदि आवश्यक हो, तो इसे बंद करें और केवल तभी कहें कि आपको क्षेत्रों को भरने और लाइनों को खींचने की आवश्यकता है। परिणाम:







यदि हम इसी घुमाव के साथ कुछ और किनारों को जोड़ते हैं, तो हमें एक हिमपात होता है:



function drawFlake(x, y, len, n, stroke, fill) {

sky.save(); sky.strokeStyle = stroke;

sky.fillStyle = fill;

sky.beginPath();

sky.translate(x, y);

sky.moveTo(0, 0); leg(n, len); sky.rotate(-120 * deg);

leg(n, len); sky.rotate(-120 * deg);

leg(n, len);
sky.closePath();

sky.fill();

sky.stroke();

sky.restore();

}








परिणाम:







बर्फ के टुकड़े बनाना और बढ़ना





इसके अलावा, यह विचार काफी पारदर्शी है: 1) टाइमर पर स्नोफ्लेक्स के जोड़ को लटकाकर स्नोफ्लेक्स का एक पूल बनाएं, 2) टाइमर द्वारा, स्नोफ्लेक्स की स्थिति बदलें और ड्रा करें।



स्नोफ्लेक्स जोड़ना




यादृच्छिक मूल्यों के लिए अतिरिक्त कार्य, स्नोफ्लेक की एक सरणी और अधिकतम संख्या। टाइमर सेट करें:



var rand = function (n) { return Math.floor(n * Math.random()); }

var flakes = []; var maxflakes = 20;

var snowspeed = 500;

var snowingTimer = setInterval(createSnowflake, snowspeed);








और वास्तव में स्नोफ्लेक्स का निर्माण (सही समय पर, टाइमर की सफाई से नए स्नोफ्लेक्स का निर्माण बंद हो जाता है):



function createSnowflake() {

var order = 3;

var size = 10 + rand(50);

var x = rand( document .body.offsetWidth);

var y = window.pageYOffset;



flakes.push({ x: x, y: y, vx: 0, vy: 3 + rand(3), size: size, order: order, stroke: "#99f" , fill: "transparent" });

if (flakes.length > maxflakes) clearInterval(snowingTimer);

}








चल रहे हिमकण




यहां एक अतिरिक्त वैरिएबल अमान्यता दिखाई देती है, जो स्क्रीन आकार बदलते समय सही पर सेट होती है। हम स्थिति और वास्तविक आंदोलन फ़ंक्शन को अपडेट करने के लिए टाइमर सेट करते हैं (स्क्रीन साफ़ करें, स्थिति अपडेट करें -> स्नोफ्लेक ड्रा करें)।



var scrollspeed = 64;

setInterval(moveSnowflakes, scrollspeed);



function moveSnowflakes() {

sky.clearRect(0, 0, canvas.width, canvas.height);



var maxy = canvas.height;



for ( var i = 0; i < flakes.length; i++) {

var flake = flakes[i];

flake.y += flake.vy;

flake.x += flake.vx;



if (flake.y > maxy) flake.y = 0;

if (invalidateMeasure) {

flake.x = rand(canvas.width);

}



drawFlake(flake.x, flake.y, flake.size, flake.order, flake.stroke, flake.fill);



//

if (rand(4) == 1) flake.vx += (rand(11) - 5) / 10;

if (flake.vx > 2) flake.vx = 2;

if (flake.vx < -2) flake.vx = -2;

}

if (invalidateMeasure) invalidateMeasure = false ;

}








अंतिम कोड





इसके अलावा, आप कुछ अतिरिक्त विवरण जोड़ सकते हैं: हिमपात का एक यादृच्छिक घुमाव और हिमपात का एक यादृच्छिक रंग + आकार के आधार पर विवरण:



( function () {

if ( document .createElement( 'canvas' ).getContext) {

if ( document .readyState === 'complete' )

snow();

else

window.addEventListener( 'DOMContentLoaded' , snow, false );

}

else {

return ;

}



var deg = Math.PI / 180;

var maxflakes = 20; var flakes = []; var scrollspeed = 64; var snowspeed = 500;

var canvas, sky;

var snowingTimer;

var invalidateMeasure = false ;



var strokes = [ "#6cf" , "#9cf" , "#99f" , "#ccf" , "#66f" , "#3cf" ];



function rand (n) {

return Math.floor(n * Math.random());

}



//

function snow() {

canvas = document .createElement( 'canvas' );

canvas.style.position = 'fixed' ;

canvas.style.top = '0px' ;

canvas.style.left = '0px' ;

canvas.style.zIndex = '-10' ;



document .body.insertBefore(canvas, document .body.firstChild);

sky = canvas.getContext( '2d' );



ResetCanvas();



snowingTimer = setInterval(createSnowflake, snowspeed);

setInterval(moveSnowflakes, scrollspeed);

window.addEventListener( 'resize' , ResetCanvas, false );

}



// Canvas

function ResetCanvas() {

invalidateMeasure = true ;

canvas.width = document .body.offsetWidth;

canvas.height = window.innerHeight;

}



//

function leg(n, len) {

sky.save(); //

if (n == 0) { // -

sky.lineTo(len, 0); }

else {

sky.scale(1 / 3, 1 / 3); // 3

leg(n - 1, len); sky.rotate(60 * deg);

leg(n - 1, len); sky.rotate(-120 * deg);

leg(n - 1, len); sky.rotate(60 * deg); leg(n - 1, len); }

sky.restore(); //

sky.translate(len, 0); //

}



//

function drawFlake(x, y, angle, len, n, stroke, fill) {

sky.save(); sky.strokeStyle = stroke;

sky.fillStyle = fill;

sky.beginPath();

sky.translate(x, y);

sky.moveTo(0, 0); sky.rotate(angle);

leg(n, len);

sky.rotate(-120 * deg);

leg(n, len); sky.rotate(-120 * deg);

leg(n, len); sky.closePath();

sky.fill();

sky.stroke();

sky.restore();

}



//

function createSnowflake() {

var order = 2+rand(2);

var size = 10*order+rand(10);

var x = rand( document .body.offsetWidth);

var y = window.pageYOffset;

var stroke = strokes[rand(strokes.length)];



flakes.push({ x: x, y: y, vx: 0, vy: 3 + rand(3), angle:0, size: size, order: order, stroke: stroke, fill: 'transparent' });



if (flakes.length > maxflakes) clearInterval(snowingTimer);

}



//

function moveSnowflakes() {

sky.clearRect(0, 0, canvas.width, canvas.height);



var maxy = canvas.height;



for ( var i = 0; i < flakes.length; i++) {

var flake = flakes[i];



flake.y += flake.vy;

flake.x += flake.vx;



if (flake.y > maxy) flake.y = 0;

if (invalidateMeasure) {

flake.x = rand(canvas.width);

}



drawFlake(flake.x, flake.y, flake.angle, flake.size, flake.order, flake.stroke, flake.fill);



//

if (rand(4) == 1) flake.vx += (rand(11) - 5) / 10;

if (flake.vx > 2) flake.vx = 2;

if (flake.vx < -2) flake.vx = -2;

if (rand(3) == 1) flake.angle = (rand(13) - 6) / 271;

}

if (invalidateMeasure) invalidateMeasure = false ;

}

} ());





* This source code was highlighted with Source Code Highlighter .








कोड को कॉपी करें, कंसोल से चलाएं और साइट पर बर्फबारी करें।



All Articles