2012-10-03 12 views
8

क्या एचटीएमएल 5 में टेक्स्ट लेटर (ओं) से पथ निकालने के लिए वैसे भी है, फिर उस पथ के साथ (x, y) निर्देशांक को पकड़ें ताकि पत्रों को मंडलियों के साथ बनाया जा सके वह पत्र पथ?टेक्स्ट एचटीएमएल कैनवास से पथ निकालें

मैं एक्स, वाई निर्देशांक लेना चाहता हूं और उनके स्थान पर एक आकार लागू करना चाहता हूं ताकि यह "एनिमेटिंग प्रभाव" के बाद "पिक्सेलेटेड" प्रारूप में पाठ की स्ट्रिंग जैसा दिखता हो।

कैनवास पर वर्णों के पथ के साथ किसी प्रकार का एक्स, वाई निर्देशांक प्राप्त करने पर कोई सलाह बहुत अच्छी होगी।

संपादित करें: http://www.html5canvastutorials.com/labs/html5-canvas-google-bouncing-balls/

+0

संभव डुप्लिकेट http://stackoverflow.com/questions/19954058/html5-canvas-text- चौराहे) –

उत्तर

8

यह नेत्रहीन एक पत्र के मार्ग के किनारे हलकों रखकर मैन्युअल रूप से करना करने के लिए एक मुश्किल काम है: मैं अनिवार्य रूप से इस के समान कुछ करने के लिए स्वत: करने के लिए कोशिश कर रहा हूँ निर्देशांक उत्पन्न।

मानव हस्तक्षेप के बिना (स्वचालित रूप से!) स्वचालित रूप से कठिन है।

यहां पत्र बनाने के लिए स्वचालित रूप से मंडलियों की व्यवस्था करने का तरीका बताया गया है।

जवाब "letterform",

  • मंडलियां बनाना भरने और letterform की रूपरेखा तैयार करने ढूँढना 2 भागों में है ...

    1. कठिन हिस्सा

    फ्रेडरिक डी Bleser कोडित है एक अच्छा पुस्तकालय opentype.js कि एक .ttf फ़ॉन्ट फ़ाइल लेता है और एक कैनवास पर द्विघात घटता का उपयोग कर किसी भी निर्दिष्ट चरित्र की ग्लिफ़ रूपरेखा बाहर पार्स करता है कहा जाता है: https://github.com/nodebox/opentype.js

    2. केवल थोड़ा कम कठिन हिस्सा

    प्रत्येक अक्षर के लिए:

    • प्रत्येक वर्गिक वक्र पर "कई" अंक खोजें। एक अंतराल पर वक्र पर एक [x, y] की गणना करने के लिए एल्गोरिदम है, वक्र के अंत में वक्र की शुरुआत में 0.00 से 0.00 तक होगा। टी वक्र के साथ समान रूप से दूरी [x, y] का उत्पादन नहीं करेगा, इसलिए आपको oversample करने की आवश्यकता होगी (इसलिए "कई" का अर्थ 0.00 और 1.00 के बीच टी के 1000 मान हो सकता है)।

      function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) { 
          var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x; 
          var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y; 
          return({x:x,y:y}); 
      } 
      
    • कोण उन बिंदुओं पर वक्र के कोण करने के लिए स्पर्श रेखा होती है कि पता लगाएं। (मूल रूप से गणना करें कि वक्र के लिए सही कोण क्या होगा)। आप द्विघात सूत्र के अगले व्युत्पन्न के साथ ऐसा कर सकते हैं:

      function quadraticBezierTangentAngle(t, p0, p2, p1) { 
          var tt = 1 - t; 
          var dx = (tt * p1.x + t * p2.x) - (tt * p0.x + t * p1.x); 
          var dy = (tt * p1.y + t * p2.y) - (tt * p0.y + t * p1.y); 
          return Math.tan(Math.atan2(dy,dx)); 
      } 
      
    • वक्र की शुरुआत में शुरू, के बगल में [, वाई x] से वर्तमान प्रत्येक दूरी [एक्स, वाई] की गणना।आप पाइथागोरस प्रमेय के साथ ऐसा कर सकते हैं:

      var dx=nextX-currentX; 
      var dy=nextY-currentY; 
      var distance=Math.sqrt(dx*dx+dy*dy); 
      
    • सरणी ताकि सभी शेष [एक्स, वाई] तत्वों पिछले [एक्स, वाई] तत्व से 1px दूर हैं डी-डुप्लिकेट। आप इसे पहले से मूल्यों के साथ एक दूसरा सरणी भरकर कर सकते हैं जहां parseInt(nextInOriginalArray - lastDistanceInNewArray)==1;

    • प्रत्येक मंडल के लिए एक त्रिज्या पर निर्णय लें जो प्रत्येक पत्र को बनाएगा। ऐसा लगता है कि यह वास्तव में कठिन है। "ब्लॉककी" फोंट के लिए, आप कैनवास पर "I" अक्षर खींच सकते हैं। फिर getImageData का उपयोग कर सभी पिक्सेल लाएं। पत्र के ऊर्ध्वाधर मध्य में क्षैतिज रूप से चल रहे अपारदर्शी पिक्सल की गिनती की खोज करके "I" के ऊर्ध्वाधर स्ट्रोक की चौड़ाई की गणना करें। ब्लॉकी फोंट के लिए, var radius = horizontalOpaquePixelCount/2;। परिवर्तनीय चौड़ाई स्ट्रोक वाले फोंट के लिए, आपको आविष्कारक होना होगा। शायद var radius = horizontalOpaquePixelCount/3; या var radius = horizontalOpaquePixelCount/4;

    • अंक सरणी के माध्यम से Iterate और हर radius*2 पिक्सेल एक नया सर्कल परिभाषित करें।

      var centerX = curvePointX + radius*Math.cos(tangentAngle); 
      var centerY = curvePointY + radius*Math.sin(tangentAngle); 
      
    • हलकों बनाते समय कुछ बिंदु पत्र के घटता खुद पर वापस हो जाएगा पर, है, तो आप प्रत्येक नए वृत्त आपके द्वारा बनाए गए चेक करना होगा: आप स्पर्श कोण और इस तरह त्रिकोणमिति का उपयोग कर प्रत्येक चक्र के लिए केंद्र बिंदु की गणना यह सुनिश्चित करने के लिए कि यह मौजूदा सर्कल को ओवरलैप नहीं करेगा। आप गणना कर सकते हैं एक नया चक्र इस तरह प्रत्येक मौजूदा मंडली एक दूसरे को काटना होगा कि क्या:

      var dx = newCircleCenterX - existingCircleCenterX; 
      var dy = newCircleCenterY - existingCircleCenterY; 
      var distance=Math.sqrt(dx*dx+dy*dy); 
      var circlesAreIntersecting=(distance<=newCircleRadius+existingCircleRadius); 
      

    ठीक ट्यूनिंग: पत्र के मार्ग में कुछ अंतिमबिंदुओं अंक के पास, तो आप पाएंगे कि एक अगली पूर्ण त्रिज्या सर्कल से बाहर गिर जाएगा लेटरफॉर्म यदि ऐसा होता है तो आप लेटरफॉर्म फिट करने के लिए कुछ मंडलियों के त्रिज्या को कम कर सकते हैं। यदि आप अपनी मंडलियों के लिए पूरी तरह से एक निश्चित त्रिज्या चाहते हैं तो आप सभी मंडलियों के औसत त्रिज्या के आधार पर सभी मंडलियों के निश्चित त्रिज्या को फिर से समझ सकते हैं - जिनमें से आपको लेटरफॉर्म फिट करने के लिए "सिकुड़ना" था।

    उदाहरण के लिए

    । यह

    enter image description here

    लेकिन 2 लाल हलकों अपने letterform के बाहर गिर पत्र "एल 15 हलकों द्वारा गठित है।। आप सकता है (1) लाल हलकों letterform या (2) पुनर्गणना के अंदर फिट करने के लिए हटना एक नया तय सर्कल त्रिज्या औसत त्रिज्या के आधार पर कि letterform फिट बैठता है: (1) रेखा खंड:

    var total=0; 
    total += greenRadii * 13; 
    total += verticalRedRadiusResizedToFitInsideLetterform; 
    total += horizontalRedRadiusResizedToFitInsideLetterform; 
    var newRadius = total/15; 
    

    आप लाल त्रिज्या कि 2 लाइनों के चौराहे की गणना के द्वारा letterform फिट होगा की अवधि की गणना कर सकते हैं अंतिम हरे सर्किल केंद्र और लाल मंडल केंद्र को जोड़कर गठित किया गया, (2) रेखा लंबवत रूप से बनाई गई है वक्र पर अंतिम बिंदु मीटर। यहाँ 2 लाइनों के चौराहे बिंदु की गणना करने के लिए एक एल्गोरिथ्म है:

    // Get interseting point of 2 line segments (if any) 
    // Attribution: http://paulbourke.net/geometry/pointlineplane/ 
    function line2lineIntersection(p0,p1,p2,p3) { 
    
        var unknownA = (p3.x-p2.x) * (p0.y-p2.y) - (p3.y-p2.y) * (p0.x-p2.x); 
        var unknownB = (p1.x-p0.x) * (p0.y-p2.y) - (p1.y-p0.y) * (p0.x-p2.x); 
        var denominator = (p3.y-p2.y) * (p1.x-p0.x) - (p3.x-p2.x) * (p1.y-p0.y);   
    
        // Test if Coincident 
        // If the denominator and numerator for the ua and ub are 0 
        // then the two lines are coincident.  
        if(unknownA==0 && unknownB==0 && denominator==0){return(null);} 
    
        // Test if Parallel 
        // If the denominator for the equations for ua and ub is 0 
        //  then the two lines are parallel. 
        if (denominator == 0) return null; 
    
        // If the intersection of line segments is required 
        // then it is only necessary to test if ua and ub lie between 0 and 1. 
        // Whichever one lies within that range then the corresponding 
        // line segment contains the intersection point. 
        // If both lie within the range of 0 to 1 then 
        // the intersection point is within both line segments. 
        unknownA /= denominator; 
        unknownB /= denominator; 
    
        var isIntersecting=(unknownA>=0 && unknownA<=1 && unknownB>=0 && unknownB<=1) 
    
        if(!isIntersecting){return(null);} 
    
        return({ 
         x: p0.x + unknownA * (p1.x-p0.x), 
         y: p0.y + unknownA * (p1.y-p0.y) 
        }); 
    } 
    
  • +0

    क्या आप वर्णित एल्गोरिदम के किसी भी कार्यान्वयन के बारे में जानते हैं? – seltzlab

    +0

    एल्गोरिदम की एक श्रृंखला - यह एल्गोरिदम की एक श्रृंखला से अधिक ऐप है। मेरे पास इस ऐप का लगभग 75% है। मेरे पास इसे खत्म करने का समय नहीं है। :-) – markE

    10

    पिक्सेल स्केलिंग

    इस के लिए एक साधारण दृष्टिकोण निम्न करने के लिए है:, पाठ आकर्षित एक छोटा सा फ़ॉन्ट

    • उपयोग एक ठोस रंग
    • सभी पिक्सेल Iterate का उपयोग कर।अल्फा = 255 के साथ कोई भी पिक्सेल, एक सरणी में स्टोर करता है लेकिन एक्स और वाई के साथ व्यास

    अब आपके पास टेक्स्ट का प्रतिनिधित्व करने वाली "गेंद" की एक मोटा सरणी है और एनिमेटेड हो सकती है। जब यह अक्षर अंतर की बात आती है तो यह सुपर सटीक नहीं है लेकिन इसे दिए गए उद्देश्य के लिए करना चाहिए (आप हमेशा प्रत्येक अक्षर को माप सकते हैं और अलग-अलग बिंदु पर अतिरिक्त डेल्टा मान का उपयोग करके अंतिम एक्स मान बढ़ा सकते हैं)।

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

    और आखिरकार, अलग-अलग ब्राउज़र अलग-अलग पाठ प्रस्तुत करते हैं ताकि आप इसे भी ध्यान में रखना चाहें (प्रत्येक पत्र को मापने के बारे में ऊपर देखें) उनके बीच अतिरिक्त जगह जोड़ने के लिए।

    डेमो

    snapshot

    var ctx = document.querySelector("canvas").getContext("2d"), 
     
        inp = document.querySelector("input"), 
     
        w = ctx.canvas.width, 
     
        h = ctx.canvas.height, 
     
        balls = [];          // global ball array 
     
    
     
    ctx.fillStyle = "rgb(0, 154, 253)";     // fill must be a solid color 
     
    generate(inp.value)         // init default text 
     
    inp.onkeyup = function() {generate(this.value)}; // get some text to demo 
     
    
     
    function generate(txt) { 
     
        var i, radius = 5,        // ball radius 
     
         data32;          // we'll use uint32 for speed 
     
        
     
        balls = [];          // clear ball array 
     
        ctx.clearRect(0, 0, w, h);      // clear canvas so we can 
     
        ctx.fillText(txt.toUpperCase(), 0, 10);   // draw the text (default 10px) 
     
        
     
        // get a Uint32 representation of the bitmap: 
     
        data32 = new Uint32Array(ctx.getImageData(0, 0, w, h).data.buffer); 
     
        
     
        // loop through each pixel. We will only store the ones with alpha = 255 
     
        for(i = 0; i < data32.length; i++) { 
     
        if (data32[i] & 0xff000000) {    // check alpha mask 
     
         balls.push({       // add new ball if a solid pixel 
     
         x: (i % w) * radius * 2 + radius,  // use position and radius to 
     
         y: ((i/w)|0) * radius * 2 + radius, // pre-calc final position and size 
     
         radius: radius, 
     
         a: (Math.random() * 250)|0   // just to demo animation capability 
     
         }); 
     
        } 
     
        } 
     
        // return array - here we'll animate it directly to show the resulting objects: 
     
    } 
     
    
     
    (function animate() { 
     
        ctx.clearRect(0, 0, w, h); 
     
        ctx.beginPath(); 
     
        for(var i = 0, ball; ball = balls[i]; i++) { 
     
        var dx = Math.sin(ball.a * 0.2) + ball.radius, // do something funky 
     
         dy = Math.cos(ball.a++ * 0.2) + ball.radius; 
     
        ctx.moveTo(ball.x + ball.radius + dx, ball.y + dy); 
     
        ctx.arc(ball.x + dx, ball.y + dy, ball.radius, 0, 6.28); 
     
        ctx.closePath(); 
     
        } 
     
        ctx.fill(); 
     
        requestAnimationFrame(animate); 
     
    })();
    body {font:bold 16px sans-serif}
    <label>Type some text: <input value="PIXELS"></label><br> 
     
    <canvas width=1024></canvas>

    [HTML5 कैनवास पाठ चौराहों] (की
    संबंधित मुद्दे