2012-09-21 10 views
8

मैं (जैसे JavaScript कंसोल में प्रवेश) एक png निम्नलिखित स्निपेट का उपयोग करने के this page पर canvas तत्व परिवर्तित करने के लिए कोशिश कर रहा हूँ:छवि में कनवर्ट करने के बाद मेरा कैनवास खाली क्यों जाता है?

(function convertCanvasToImage(canvas) { 
    var image = new Image(); 
    image.src = canvas.toDataURL("image/png"); 
    return image; 
})($$('canvas')[0]); 

दुर्भाग्य से, png मैं पूरी तरह से खाली है। ध्यान दें कि पृष्ठ का आकार बदलने के बाद मूल कैनवास खाली हो जाता है।

canvas क्यों खाली है? मैं इस canvas को एक पीएनजी में कैसे परिवर्तित कर सकता हूं?

+0

आप किसी भी त्रुटि मिल सकता है? '$$' एक टाइपो है, या क्या आपके पास सिंगल, डॉलर चिह्न के बजाए डबल का उपयोग करके jQuery है? – MrOBrian

+1

'' $$ एक क्रोम JavaScript कंसोल, जो jQuery की तरह ही बर्ताव करने के लिए समारोह में बनाया गया है। मुझे कोई त्रुटि नहीं मिली, नहीं। – Randomblue

+0

आह, उसे नहीं पता था ... मुझे लगता है कि उस पृष्ठ के साथ कुछ चल रहा है। यदि मैं उस पृष्ठ पर कैनवास पर 'toDataURL()' करता हूं तो मुझे 500x500 खाली छवि मिलती है और कैनवास साफ़ हो जाता है। यदि मैं साइट पर एक ही कोड करता हूं तो मैं उस कैनवास का उपयोग कर रहा हूं, मुझे सही डेटा मिलता है और कैनवास साफ़ नहीं होता है। – MrOBrian

उत्तर

14

केविन रीड का preserveDrawingBuffer सुझाव सही है, लेकिन (आमतौर पर) एक बेहतर विकल्प है। टीएल; डॉ अंत में कोड है।

एक प्रस्तुत वेबपृष्ठ के अंतिम पिक्सल को एक साथ रखना महंगा हो सकता है, और यह भी समन्वय कर सकता है कि वेबजीएल सामग्री को और भी प्रस्तुत करने के साथ। सामान्य प्रवाह है:

  1. जावास्क्रिप्ट
  2. जावास्क्रिप्ट रिटर्न WebGL संदर्भ के आदेशों ड्राइंग, मुख्य ब्राउज़र घटना पाश
  3. WebGL संदर्भ के लिए कंपोज़िटर के लिए खत्म हो बफर (या इसकी सामग्री) ड्राइंग बदल जाता है करने के लिए नियंत्रण लौटने मुद्दों वेब पेज में एकीकरण वर्तमान में WebGL सामग्री वाले स्क्रीन पर प्रदान की गई किया जा रहा
  4. पृष्ठ, स्क्रीन पर प्रदर्शित

ध्यान दें कि यह सबसे ओपन अनुप्रयोगों से अलग है। उन में, प्रस्तुत सामग्री आमतौर पर किसी पृष्ठ पर अन्य सामानों के समूह के साथ मिश्रित होने के बजाय सीधे प्रदर्शित होती है, जिनमें से कुछ वास्तव में वेबजीएल सामग्री के शीर्ष पर और मिश्रित हो सकती हैं।

WebGL कल्पना ड्राइंग बफर के रूप में अनिवार्य रूप से चरण 3. कोड आप DevTools में चला रहे हैं चरण 4, जिसके कारण आप एक खाली बफर प्राप्त करने के बाद आ रहा है के बाद खाली इलाज के लिए बदल गया था। इस बदलाव में इस प्लेटफॉर्म पर बड़े प्रदर्शन सुधार की अनुमति दी गई है जहां चरण 3 के बाद रिक्त स्थान मूल रूप से हार्डवेयर में होता है (जैसे कई मोबाइल जीपीयू)। यदि आप चरण 3 के बाद कभी-कभी वेबजीएल सामग्री की प्रतियां बनाने के लिए काम करना चाहते हैं, तो ब्राउज़र को हमेशा चरण 3 से पहले ड्रॉइंग बफर की प्रतिलिपि बनाना होगा, जो कुछ प्लेटफार्मों पर आपके फ़्रेमेट ड्रॉप को तेजी से छोड़ने जा रहा है।

आप ठीक से ऐसा कर सकते हैं और ब्राउजर को प्रतिलिपि बनाने के लिए मजबूर कर सकते हैं और preserveDrawingBuffer को सही पर सेट करके छवि सामग्री को सुलभ रख सकते हैं। Spec से:

यह डिफ़ॉल्ट व्यवहार WebGLContextAttributes ऑब्जेक्ट की संरक्षित ड्रॉइंगबफर विशेषता को सेट करके बदला जा सकता है। यदि यह ध्वज सत्य है, तो ड्रॉइंग बफर की सामग्री तब तक संरक्षित की जाएगी जब तक कि लेखक या तो उन्हें साफ़ या ओवरराइट नहीं करता।यदि यह ध्वज गलत है, तो प्रतिपादन फ़ंक्शन लौटने के बाद स्रोत संदर्भ के रूप में इस संदर्भ का उपयोग करके संचालन करने का प्रयास अपरिभाषित व्यवहार का कारण बन सकता है। इसमें readPixels या ToDataURL कॉल शामिल हैं, या इस संदर्भ का उपयोग किसी अन्य संदर्भ के texImage2D या drawImage कॉल की स्रोत छवि के रूप में करते हैं।

gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true}); 

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

उदाहरण आपके द्वारा दी गई है, कोड सिर्फ संदर्भ निर्माण लाइन बदल रहा है आप क्या और कैसे प्रतिपादन कर रहे हैं। आप सबसे डेस्कटॉप ब्राउज़र है, जहां प्रति वास्तव में किए जाने के लिए नहीं है में ठीक होना चाहिए, और उन WebGL सक्षम ब्राउज़रों के विशाल बहुमत बना है ... लेकिन केवल अब के लिए।

हालांकि, वहाँ एक और विकल्प है (के रूप में कुछ हद तक भ्रामक रूप से कल्पना में अगले पैराग्राफ में उल्लेख किया है)।

अनिवार्य रूप से, आप प्रति अपने आप को बनाने के लिए चरण 2 से पहले: के बाद अपने सभी ड्रा कॉल समाप्त कर दिया है, लेकिन इससे पहले कि आप अपने कोड से ब्राउज़र को नियंत्रण वापस जाएँ। यह तब होता है जब वेबजीएल ड्राइंग बफर अभी भी व्यवहार में है और पहुंच योग्य है, और आपको तब पिक्सेल तक पहुंचने में कोई परेशानी नहीं होनी चाहिए। आप एक ही toDataUrl या readPixels कॉल आप अन्यथा का प्रयोग करेंगे उपयोग करते हैं, यह सिर्फ समय है कि महत्वपूर्ण है।

यहाँ आप दोनों दुनिया का सबसे अच्छा मिलता है। आप ड्राइंग बफर की एक प्रति प्राप्त है, लेकिन आप हर फ्रेम में इसके लिए भुगतान नहीं करते हैं, यहां तक ​​कि उन है जिसमें आप एक प्रति (जो उनमें से ज्यादातर हो सकता है) की ज़रूरत नहीं थी जैसे आप सत्य पर preserveDrawingBuffer सेट के साथ करते हैं।

उदाहरण आपके द्वारा दी गई में, बस drawScene के नीचे करने के लिए अपने कोड जोड़ सकते हैं और आप सही नीचे कैनवास की प्रतिलिपि देखना चाहिए:

function drawScene() { 
    ... 

    var webglImage = (function convertCanvasToImage(canvas) { 
    var image = new Image(); 
    image.src = canvas.toDataURL('image/png'); 
    return image; 
    })(document.querySelectorAll('canvas')[0]); 

    window.document.body.appendChild(webglImage); 
} 
+1

धन्यवाद। यह बताता है कि पीएनजी छवि खाली क्यों थी, लेकिन यह स्पष्ट नहीं करता कि क्यों * मूल छवि * खाली हो जाती है। – Randomblue

+1

यह सिर्फ मेरे लिए {preserveDrawingBuffer: true} हिस्सा था, हालांकि महान जवाब – FrickeFresh

2

यहां कुछ चीजों को आजमाने की कोशिश है। मुझे नहीं पता कि इनमें से कोई भी इस काम को करने के लिए आवश्यक होना चाहिए, लेकिन वे एक अंतर डाल सकते हैं।

  • getContext विशेषताओं के preserveDrawingBuffer: true जोड़ें।
  • इसे बाद के ट्यूटोरियल के साथ करने का प्रयास करें जो एनीमेशन करता है; यानी कैनवास पर बार-बार बार-बार खींचता है।
संबंधित मुद्दे