سؤال

ما أود القيام به هو رسم رسوماتاتي على المخزن المؤقت ثم أتمكن من نسخها كما هو الحال مع القماش حتى أتمكن من القيام بالرسوم المتحركة وتجنب الخفقان. لكنني لم أجد هذا الخيار. أي شخص يعرف كيف يمكنني القيام بهذا؟

هل كانت مفيدة؟

المحلول

يوضح الرابط المفيد التالي ، بالإضافة إلى إظهار الأمثلة والمزايا لاستخدام التخزين المؤقت المزدوج ، العديد من نصائح الأداء الأخرى لاستخدام عنصر Canvas HTML5. ويشمل روابط لاختبارات JSPERF ، والتي تنتج نتائج الاختبار عبر المتصفحات في قاعدة بيانات متصفح. هذا يضمن التحقق من نصائح الأداء.

http://www.html5rocks.com/en/tutorials/canvas/performance/

لراحتك ، قمت بتضمين مثال أدنى من التخزين المؤقت المزدوج الفعال كما هو موضح في المقالة.

// canvas element in DOM
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');

// buffer canvas
var canvas2 = document.createElement('canvas');
canvas2.width = 150;
canvas2.height = 150;
var context2 = canvas2.getContext('2d');

// create something on the canvas
context2.beginPath();
context2.moveTo(10,10);
context2.lineTo(10,30);
context2.stroke();

//render the buffered canvas onto the original canvas element
context1.drawImage(canvas2, 0, 0);

نصائح أخرى

هناك طريقة بسيطة للغاية تتمثل في وجود اثنين من العناصر القماشية في نفس موقع الشاشة وضبط الرؤية للمخزن المؤقت الذي تحتاج إلى عرضه. ارسم على المخفي وقلب عند الانتهاء.

بعض الكود:

CSS:

canvas { border: 2px solid #000; position:absolute; top:0;left:0; 
visibility: hidden; }

التقليب في JS:

Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';

DrawingBuffer=1-DrawingBuffer;

في هذا الرمز ، يحمل الصفيف "المخازن المؤقتة [] كلا من القماش. لذلك عندما تريد البدء في الرسم ، لا تزال بحاجة إلى الحصول على السياق:

var context = Buffers[DrawingBuffer].getContext('2d');

المتصفحات التي اختبرتها جميعها تتعامل مع هذا التخزين المؤقت لك من خلال عدم إعادة طلاء القماش حتى يكتمل الرمز الذي يرسم إطارك. انظر أيضًا القائمة البريدية Whatwg: http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html

يمكنك دائما أن تفعلvar canvas2 = document.createElement("canvas");وليس إلحاقها إلى DOM على الإطلاق.

فقط تقول لأنك تبدو يا رفاق مهووسون بها display:none;يبدو الأمر أكثر نظافة بالنسبة لي ويحاكي فكرة التخزين المؤقت المزدوج بدقة أكبر من مجرد وجود قماش غير مرئي بشكل محرج.

بعد أكثر من عامين:

ليست هناك حاجة لتنفيذ "يدويًا" للتخزين المؤقت المزدوج. كتب السيد جيري عن هذا في كتابه "HTML5 Canvas".

لتقليل استخدام وميض بفعالية requestAnimationFrame()!

سأل جوش (لفترة من الوقت) عن كيفية يعرف المتصفح "عندما تنتهي عملية الرسم" لتجنب وميض. كنت سأعلق مباشرة على منصبه لكن مندوبي ليس مرتفعًا بما فيه الكفاية. أيضا هذا هو رأيي فقط. ليس لدي حقائق لدعمها ، لكنني أشعر بالثقة إلى حد ما حيال ذلك وقد يكون من المفيد للآخرين قراءة هذا في المستقبل.

أظن أن المتصفح لا "يعرف" عند الانتهاء من الرسم. ولكن تمامًا مثل معظم JavaScript ، طالما أن الكود الخاص بك يعمل دون التخلي عن التحكم في المتصفح ، فإن المتصفح محصل بشكل أساسي ولن يتمكن/لا يمكن تحديثه/الاستجابة لاتصاله. أظن أنه إذا قمت بمسح القماش ورسمت إطارك بالكامل دون التخلي عن التحكم في المتصفح ، فلن يرسم القماش الخاص بك حتى تنتهي.

إذا قمت بإعداد موقف حيث يمتد عرضك على العديد من المكالمات/setInterval/requestAnimationFrame ، حيث تقوم بمسح القماش في مكالمة واحدة ورسم عناصر على القماش الخاص بك في المكالمات العديدة التالية ، وتكرار الدورة (على سبيل المثال) كل 5 مكالمات ، أنا "D كن على استعداد للمراهنة عليك أن ترى وميض منذ أن تم تحديث القماش بعد كل مكالمة.

ومع ذلك ، لست متأكدًا من أنني أثق في ذلك. نحن بالفعل في مرحلة أن JavaScript يتم تجميعها إلى رمز الجهاز الأصلي قبل التنفيذ (على الأقل هذا ما يفعله محرك V8 من Chrome مما أفهمه). لن أتفاجأ إذا لم يمض وقت طويل قبل أن تبدأ المتصفحات في تشغيل JavaScript في مؤشر ترابط منفصل عن واجهة المستخدم ومزامنة أي وصول إلى عناصر واجهة المستخدم التي تسمح لاتصالات واجهة المستخدم بالتحديث/الاستجابة أثناء تنفيذ JavaScript لم يكن الوصول إلى واجهة المستخدم. عندما/إذا حدث ذلك (وفهمت أن هناك العديد من العقبات التي يجب التغلب عليها ، مثل انطلاق معالجات الأحداث أثناء قيامك بتشغيل رمز آخر) ، فمن المحتمل أن نرى وميض على الرسوم المتحركة التي لا تستخدم نوع من التعقيد المزدوج.

أنا شخصياً أحب فكرة عنصرين من القماش الموضوعة فوق بعضهما البعض والمتناوب الذي يتم عرضه/رسمه على كل إطار. غير متناظر إلى حد ما وربما تمت إضافته بسهولة إلى تطبيق موجود مع بضعة أسطر من التعليمات البرمجية.

بالنسبة للكافرين ، إليك بعض رمز الخفقان. لاحظ أنني أقوم بمسح الدائرة السابقة بشكل صريح.

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

function draw_ball(ball) {
    ctx.clearRect(0, 0, 400, 400);
    ctx.fillStyle = "#FF0000";
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, 30, 0, Math.PI * 2, true);
    ctx.closePath();
    ctx.fill();
}

var deltat = 1;
var ball = {};
ball.y = 0;
ball.x = 200;
ball.vy = 0;
ball.vx = 10;
ball.ay = 9.8;
ball.ax = 0.1;

function compute_position() {
    if (ball.y > 370 && ball.vy > 0) {
        ball.vy = -ball.vy * 84 / 86;
    }
    if (ball.x < 30) {
        ball.vx = -ball.vx;
        ball.ax = -ball.ax;
    } else if (ball.x > 370) {
        ball.vx = -ball.vx;
        ball.ax = -ball.ax;
    }
    ball.ax = ball.ax / 2;
    ball.vx = ball.vx * 185 / 186;
    ball.y = ball.y + ball.vy * deltat + ball.ay * deltat * deltat / 2
    ball.x = ball.x + ball.vx * deltat + ball.ax * deltat * deltat / 2
    ball.vy = ball.vy + ball.ay * deltat
    ball.vx = ball.vx + ball.ax * deltat
    draw_ball(ball);
}

setInterval(compute_position, 40);
<!DOCTYPE html>
<html>
<head><title>Basketball</title></head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</body></html>

لا يوجد وميض في متصفحات الويب! أنها تستخدم بالفعل DBL التخزين المؤقت لتقديمهم. سيجعل محرك JS كل ما تبذلونه من العرض قبل عرضه. أيضًا ، Save Context Save واستعادة فقط بيانات المصفوفة التحويلية وما شابه ، وليس محتوى القماش نفسه. لذلك ، لا تحتاج أو تريد التخزين المؤقت DBL!

بدلاً من التدحرج الخاص بك ، من المحتمل أنك ستحصل على أفضل عدد من الأميال باستخدام مكتبة موجودة لإنشاء رسوم متحركة نظيفة وخالية من وميض:

ها هي شعبية: http://processingjs.org

تحتاج إلى 2 قماش: (لاحظ مؤشر CSS Z والموقف: مطلق)

<canvas id="layer1" width="760" height="600" style=" position:absolute; top:0;left:0; 
visibility: visible;  z-index: 0; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="layer2" width="760" height="600" style="position:absolute; top:0;left:0; 
visibility: visible;  z-index: 1; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>

يمكنك أن تلاحظ أن اللوحة الأولى مرئية والثاني مخفي الفكرة التي يجب أن تستمدها المخفية بعد ذلك سوف نخفي المرئي ونجعل اللوحة الخفية مرئية. عندما تكون مخفية "قماش مخفي واضح

<script type="text/javascript">
var buff=new Array(2);
buff[0]=document.getElementById("layer1");
buff[1]=document.getElementById("layer2");

ctx[0]=buff[0].getContext("2d");
ctx[1]=buff[1].getContext("2d");
var current=0;
// draw the canvas (ctx[ current ]);
buff[1- current ].style.visibility='hidden';
buff[ current ].style.visibility='visible';
ctx[1-current].clearRect(0,0,760,600);
current =1-current;

أوبرا 9.10 بطيئة للغاية وتظهر عملية الرسم. إذا كنت ترغب في رؤية متصفح لا يستخدم التخزين المؤقت المزدوج ، فحاول Opera 9.10 Out.

اقترح بعض الأشخاص أن المتصفحات تحدد بطريقة ما متى تنتهي عملية الرسم ولكن هل يمكنك شرح كيف يمكن أن يعمل ذلك؟ لم ألاحظ أي وميض واضح في Firefox ، Chrome ، أو IE9 حتى عندما يكون الرسم بطيئًا ، يبدو أن هذا هو ما يفعلونه ولكن كيف يتم إنجازه هو لغز بالنسبة لي. كيف سيعرف المتصفح أن هذا ينعش الشاشة قبل تنفيذ المزيد من تعليمات الرسم؟ هل تعتقد أنهم مجرد وقت ذلك ، لذا إذا كان هناك فاصل أكثر من 5 مللي ثانية أو نحو ذلك دون تنفيذ تعليمات رسم قماش ، فهذا يفترض أنه يمكنه تبديل المخازن المؤقتة بأمان؟

في معظم المواقف ، لا تحتاج إلى القيام بذلك ، فإن المتصفح ينفذ هذا لك. لكن ليس مفيدًا دائمًا!

لا يزال يتعين عليك تنفيذ هذا عندما يكون الرسم معقدًا للغاية. معظم معدل تحديث الشاشة حوالي 60 هرتز ، فهذا يعني تحديثات الشاشة لكل 16 مللي ثانية. قد يكون معدل تحديث المتصفح بالقرب من هذا الرقم. إذا كان شكلك يحتاج إلى اكتمال 100 مللي ثانية ، فسترى شكلًا غير مكتمل. حتى تتمكن من تنفيذ التخزين المؤقت المزدوج في هذا الموقف.

لقد أجريت اختبارًا: Clear a rect, wait for some time, then fill with some color. إذا قمت بتعيين الوقت على 10 مللي ثانية ، فلن أرى الخفقان. ولكن إذا قمت بتعيينها على 20 مللي ثانية ، يحدث الخفقان.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top