2016-08-25 6 views
5

मेरे पास एक HTML5 कैनवास है जिस पर मैं एक svg से एक छवि खींचता हूं।जावास्क्रिप्ट: toDataUrl() फेंकना "सुरक्षा त्रुटि: चित्रित कैनवास निर्यात नहीं किया जा सकता है।"

एचटीएमएल

<canvas id="canvas" width="600" height="320"></canvas> 

जावास्क्रिप्ट

var DOMURL = window.URL || window.webkitURL || window; 

var data = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="320">'+ 
        '<foreignObject width="100%" height="100%">'+ 
         '<style>'+ 
          'foreignObject {'+ 
           'background-color: #000;'+ 
           'color: #fff'+ 
           'border-radius: 10px;'+ 
          '}'+ 
          'h1 {'+ 
           'color: #2acabd;'+ 
           'font: 25px arial;'+ 
           'font-weight: bold;'+ 
           'text-align: center;'+ 
          '}'+ 
          'h2 {'+ 
           'margin: 0;'+ 
           'color: #2acabd;'+ 
           'font: 15px arial;'+ 
          '}'+ 
          'p {'+ 
           'color: #fff;'+ 
          '}'+ 
         '</style>'+ 
         '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size: 40px;">'+ 
          '<h1>Heading</h1>'+ 
          '<div>'+ 
           '<div id="details-wrapper">'+ 
            '<h2>Full Name</h2>'+ 
            '<p>Alan Johnson</p>'+ 

            '<h2>Date of Birth</h2>'+ 
            '<p>7th November 1988</p>'+ 

            '<p><span id="user-id">34329483028493284093284432</span></p>'+ 
           '</div>'+ 
          '</div>'+ 
         '</div>'+ 
        '</foreignObject>'+ 
       '</svg>'; 


var canvas = document.getElementById("canvas"); 
var ctx = canvas.getContext("2d"); 
img = new Image(); 
img.setAttribute("crossOrigin", "anonymous"); 
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'}); 
var url = DOMURL.createObjectURL(svg); 

img.onload = function() { 
    ctx.drawImage(img, 0, 0); 
    DOMURL.revokeObjectURL(url); 
    console.log(canvas.toDataURL()); 
} 
img.src = url; 

(जे एस फिडल: https://jsfiddle.net/LondonAppDev/qnpcg8th/1/)

जब मैं canvas.toDataURL() कहते हैं, मैं हो रही है अपवाद:

012,351,
(index):98 Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. 

मैंने इस अपवाद से संबंधित स्टैक ओवरफ़्लो पर कई अन्य प्रश्न और उत्तर देखे हैं। मेरी समस्या अलग है, क्योंकि (जैसा कि आप देख सकते हैं) मैं किसी भी समय अपने svg या कैनवास में किसी अन्य डोमेन से किसी भी छवियों सहित किसी भी छवि पर नहीं हूं।

मुझे समस्या का अनुमान है कि मैं DOMURL.createObjectURL के साथ एक ऑब्जेक्ट यूआरएल बना रहा हूं।

मुझे पता है कि विभिन्न ब्राउज़रों में ऐसा करने के साथ कुछ संगतता समस्याएं हैं, हालांकि इस ऐप को केवल क्रोम में चलाने की आवश्यकता है। साथ ही, सीधे कैनवास पर पाठ खींचना एक विकल्प नहीं है, मुझे इसे एक svg के माध्यम से करना होगा।

कोई भी विचार है कि मैं इस मुद्दे के आसपास कैसे हो सकता हूं, और सफलतापूर्वक मेरे कैनवास का पीएनजी प्राप्त कर सकता हूं?

+1

क्या आपने 'createObjectURL' के बजाय डेटा यूआरएल का उपयोग करने का प्रयास किया है? – Bergi

उत्तर

12

मैंने एसबीजी को ब्लॉब के बजाय डेटा यूआरएल में परिवर्तित करके हल किया।

मैं var url = DOMURL.createObjectURL(svg); हटा दिया और इस के साथ img.src = url; लाए गए:

function buildSvgImageUrl(svg) { 
    b64 = window.btoa(svg); 
    return "data:image/svg+xml;base64," + b64; 
} 

img.src = buildSvgImageUrl(data); 

अब यह दोषरहित काम करता है।

+0

Oooooh धन्यवाद !!!!! तुमने मेरा दिन बचा लिया! –

+0

मैं खोज और खोज कर रहा था, आखिरकार मैंने खुद को "आपका समाधान" बनाया और "मेरा विचार" साझा करना चाहता था, इसलिए एक प्रश्न की खोज की और आपका जवाब पागल हो गया :) –

1

यह सुरक्षा और उपयोगकर्ता गोपनीयता कारणों था।
कैनवास पर <foreignObject> पेंट करने के लिए उपयोगकर्ताओं के बारे में कई सूचनाएं लीक हो सकती हैं, और तब तक क्रोम टीम ने सोचा कि उनके पास इसे रोकने के लिए पर्याप्त सुरक्षा उपायों नहीं थे इसलिए उन्होंने कैनवास को दांत किया।

इस मुद्दे के बारे में chromium bug report है।

लेकिन ओपी के रूप में पता चला, उनके पास एक कार्यान्वयन बग था जो डेटा प्रतिबंध संस्करणों पर इस प्रतिबंध को सेट करना भूल गया था।
मैंने इस bug report को इस तथ्य के बारे में पोस्ट किया है कि वे डेटायूआरएस के साथ कैनवास को दबाने नहीं देते हैं।

यह सब पूर्व प्रतिबंधों का लाभ उठाने के लिए नेतृत्व करता है, इसलिए क्रोम के अगले संस्करणों में, हम <foreignObject> को कैनवास पर बिना ब्लैरूर के साथ पेंट करने में सक्षम होना चाहिए।

लेकिन ध्यान दें कि सफारी के पास अभी भी एक ही प्रतिबंध है (कार्यान्वयन बग के बिना, i।e dataURI हैक वहां काम नहीं करता है), और आईई < एज <foreignObject> तत्व का समर्थन नहीं करता है और किसी भी एसवीजी को चित्रित किया गया है, और एफएफ सभी उपयोगकर्ता एजेन्ट और ओएस शैलियों को हटा देता है (जो कि आप उम्मीद कर सकते हैं उससे अलग परिणाम)।

एक असली वैकल्पिक हल तो उपयोग नहीं करने के लिए इस हैक अपने तत्वों को चित्रित प्राप्त करने के लिए, लेकिन CanvasAPI ड्राइंग तरीकों (जैसे html2canvas करता है) के साथ अपने सभी HTML आकर्षित है।

संबंधित मुद्दे