Rumah >hujung hadapan web >Tutorial H5 >Tutorial menggunakan HTML5 untuk mencapai kemahiran tutorial kesan calitan pemadam_html5

Tutorial menggunakan HTML5 untuk mencapai kemahiran tutorial kesan calitan pemadam_html5

WBOY
WBOYasal
2016-05-16 15:46:372225semak imbas

Kesan ini baru sahaja digunakan dalam projek baru-baru ini, yang agak seperti kad calar Pada peranti mudah alih, gambar dicalar untuk memaparkan gambar lain. Paparannya adalah seperti berikut:
2015511163305472.png (974×840)

DEMO sila klik di sebelah kanan: DEMO
Ini adalah perkara biasa di Internet Saya pada asalnya ingin mencari demo dalam talian dan menggunakan kaedahnya, saya dapati dalam android Kerana keperluan pelanggan, ia tidak diperlukan untuk menjadi sangat lancar pada Android, sekurang-kurangnya ia mesti boleh dimainkan, tetapi demo yang saya temui dalam talian terlalu lambat dan tidak boleh dimainkan sama sekali. Jadi saya hanya mahu menulis sendiri, dan artikel ini hanya untuk merekodkan proses penyelidikan.

Perkara pertama yang terlintas di fikiran untuk kesan mengikis ini ialah menggunakan kanvas HTML5 Dalam API kanvas, kaedah clearRect yang boleh mengosongkan piksel ialah kaedah clearRect, tetapi kaedah clearRect mengosongkan segi empat tepat kawasan. kebanyakan orang sudah terbiasa dengannya. Pemadam semuanya bulat, jadi fungsi berkuasa kawasan keratan diperkenalkan, iaitu kaedah klip. Penggunaannya sangat mudah:

Kod XML/HTMLSalin kandungan ke papan keratan
  1. ctx.save()
  2. ctx.beginPath()
  3. ctx.arc(x2,y2,a,0,2*Math.PI);
  4. ctx.clip()
  5. ctx.clearRect(0,0,canvas.width,canvas.height);
  6. ctx.restore();
  7. Kod di atas merealisasikan pemadaman kawasan bulat, iaitu, mula-mula melaksanakan laluan bulat, dan kemudian menggunakan laluan ini sebagai kawasan keratan, dan kemudian mengosongkan piksel. Satu perkara yang perlu diambil perhatian ialah anda perlu menyimpan persekitaran lukisan dahulu, dan menetapkan semula persekitaran lukisan selepas mengosongkan piksel Jika anda tidak menetapkan semula, lukisan masa hadapan akan dihadkan kepada kawasan keratan itu.

    Sekarang kesan pemadaman sudah ada, kini tiba masanya untuk menulis kesan pemadaman pergerakan tetikus saya akan menggunakan tetikus untuk menerangkannya di bawah, kerana versi mudah alih adalah serupa, iaitu, gantikan tetikus dengan permulaan sentuh, gerakan tetikus. dengan touchmove, dan mouseup dengan touchend , dan pemerolehan titik koordinat ditukar daripada e.clientX kepada e.targetTouches[0].pageX.

    Untuk melaksanakan pemadaman pergerakan tetikus, saya mula-mula terfikir untuk memadamkan kawasan bulatan di mana tetikus terletak dalam acara gerakan tetikus yang dicetuskan apabila tetikus bergerak Selepas menulisnya, saya mendapati bahawa apabila tetikus bergerak dengan sangat pantas, The kawasan tidak lagi koheren, dan kesan berikut akan kelihatan Ini jelas bukan kesan pemadam yang kita mahukan.
    2015511163949198.jpg (1103×693)

    Memandangkan semua titik tidak koheren, perkara seterusnya yang perlu dilakukan ialah menyambungkan titik ini Jika anda melaksanakan fungsi lukisan, anda boleh menyambung terus dua titik melalui lineTo dan kemudian lukis, tetapi kesan pemadaman ialah Kawasan keratan. memerlukan laluan tertutup Jika anda hanya menyambungkan dua titik, kawasan keratan tidak boleh dibentuk. Kemudian saya terfikir untuk menggunakan kaedah pengiraan untuk mengira empat koordinat titik akhir bagi segi empat tepat dalam dua kawasan pemadaman, iaitu segi empat tepat merah dalam gambar di bawah:
    2015511164105508.png (343×129)

    Kaedah pengiraan juga sangat mudah, kerana kita boleh mengetahui koordinat dua titik akhir garis yang menghubungkan dua kawasan keratan, dan juga mengetahui sejauh mana garis yang kita inginkan, koordinat empat titik akhir segi empat tepat menjadi mudah dicari, jadi terdapat Kod di bawah:
    Kod XML/HTMLSalin kandungan ke papan keratan

    1. var aasin = a*Math.sin(Math.atan((y2-y1)/(x2- x1)));
    2. var aacos = a*Math.cos(Math.atan((y2-y1)/(x2-x1)) )
    3. var x3 = x1 asin;
    4. var
    5. y3 = y1-acos
    6. var
    7. x4 = x1-asin
    8. var
    9. y4 = y1 acos; var
    10. x5
    11. = x2 asin; var y5
    12. =
    13. y2-acos; var x6 =
    14. x2
    15. -asin var y6 =
    16. y2
    17. acos;

       x1, y1 dan x2, y2 ialah dua titik akhir, dengan itu koordinat empat titik akhir diperoleh. Dengan cara ini, kawasan keratan ialah bulatan ditambah segi empat tepat dan kod itu disusun seperti berikut:
      Kod XML/HTMLSalin kandungan ke papan keratan

      1. var gegas = "ontouchstart" dalam tetingkap?true:false,//tentukan sama ada Untuk peranti mudah alih
      2.  tekan mula = segera?"touchstart":"mousedown", 
      3.  tapmove = cepat?"touchmove":"mousemove", 
      4. tapend = segera?"touchend":"mouseup";
      5. canvas.addEventListener(tapstart , function(e){
      6. e.preventDefault();
      7.  
      8.  
      9. x1 = gegas?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
      10.  
      11. y1 = cepat?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
      12.  
      13. // Padamkan kawasan bulat apabila tetikus diklik buat kali pertama dan rekod titik koordinat pertama pada masa yang sama
      14. ctx.save()
      15. ctx.beginPath()
      16. ctx.arc(x1,y1,a,0,2*Math.PI);
      17. ctx.clip()
      18. ctx.clearRect(0,0,canvas.width,canvas.height);
      19. ctx.restore();
      20.  
      21. canvas.addEventListener(tapmove, tapmoveHandler);
      22. canvas.addEventListener(tapend, function(){
      23. canvas.removeEventListener(tapmove, tapmoveHandler
      24. });
      25. //Acara ini dicetuskan apabila tetikus bergerak
      26. fungsi tapmoveHandler(e){
      27. e.preventDefault()
      28.  x2 = gegas?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
      29.  y2 = gegas?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
      30.  
      31. //Dapatkan empat titik akhir kawasan keratan antara dua titik
      32. var aasin = a*Math.sin(Math.atan((y2-y1)/(x2-x1)) );
      33. var aacos = a*Math.cos(Math.atan((y2-y1)/(x2-x1)) )
      34. var x3 = x1 asin;
      35. var
      36. y3 = y1-acos
      37. var
      38. x4 = x1-asin
      39. var
      40. y4 = y1 acos; var
      41. x5
      42. = x2 asin; var y5
      43. =
      44. y2-acos var x6
      45. =
      46. x2-asin var y6
      47. =
      48. y2 acos;   // Pastikan kesinambungan garisan, jadi lukis bulatan pada satu hujung segi empat tepat
      49. ctx.save()
      50. ctx.beginPath()
      51. ctx.arc(x2,y2,a,0,2*Math.PI);
      52. ctx.clip()
      53. ctx.clearRect(0,0,canvas.width,canvas.height);
      54. ctx.restore();
      55.  
      56. // Kosongkan piksel dalam kawasan keratan segi empat tepat
      57. ctx.save()
      58. ctx.beginPath()
      59. ctx.moveTo(x3,y3);
      60. ctx.lineTo(x5,y5);
      61. ctx.lineTo(x6,y6);
      62. ctx.lineTo(x4,y4);
      63. ctx.closePath();
      64. ctx.clip()
      65. ctx.clearRect(0,0,canvas.width,canvas.height);
      66. ctx.restore();
      67.  
      68. //Rekod koordinat terakhir
      69. x1
      70. = x2; y1
      71. =
      72. y2 }
      73. })
      74. Dengan cara ini, kesan pemadaman tetikus dicapai, tetapi terdapat satu lagi perkara yang perlu dicapai, iaitu kesan kebanyakan pemadaman Apabila anda memadamkan bilangan piksel tertentu, semua kandungan imej akan dipaparkan secara automatik, ini kesan, saya menggunakan imgData untuk mencapai. Kodnya adalah seperti berikut: Salin kod
      Kod XML/HTML


      Salin kandungan ke papan keratan

      var
      imgData
      1. = ctx.getImageData(0,0,canvas.width,canvas. ketinggian); var dd
      2. =
      3. 0; untuk(var x=
      4. 0
      5. ;x<imgData.width;x =1){ untuk(var y=
      6. 0
      7. ;y<imgData.height;y =1){ var i = (y*imgData.width x)*4
      8. if(imgData.data[i 3] > 0){
      9. dd dd                                                               
      10. }
      11. }
      12. jika(dd/(imgData.width*imgData.height)
      13. <
      14. 0.4
      15. ){
      16. canvas.className = "noOp"
      17. }

        Dapatkan imgData, melintasi piksel dalam imgData, dan kemudian menganalisis alfa dalam rgba dalam tatasusunan data imgData, iaitu, menganalisis ketelusan Jika piksel dipadamkan, ketelusan akan menjadi 0, iaitu Ia adalah untuk bandingkan bilangan piksel dengan ketelusan bukan sifar dalam kanvas semasa dengan jumlah bilangan piksel pada kanvas Jika perkadaran piksel dengan ketelusan bukan sifar adalah kurang daripada 40%, ini bermakna terdapat lebih daripada 60%. daripada kawasan pada kanvas semasa Setelah dipadamkan, gambar boleh dipaparkan secara automatik.

        Perhatikan di sini bahawa saya meletakkan kod untuk menyemak piksel dalam acara naik tetikus, kerana jumlah pengiraan agak besar Jika pengguna mengklik tetikus secara liar, acara naik tetikus akan dicetuskan secara liar, yang bermaksud dia akan menjadi gila. Mencetuskan gelung itu untuk mengira piksel, jumlah pengiraan adalah sangat besar sehingga ia menyekat proses dan menyebabkan antara muka tersekat Penyelesaiannya adalah seperti berikut: tambah tamat masa untuk menangguhkan pelaksanaan pengiraan piksel dan kosongkan tamat masa setiap. masa pengguna mengklik, iaitu, jika pengguna mengklik untuk masa yang lama, pengiraan ini tidak akan dicetuskan lagi bilangan piksel terlalu besar, ia pasti akan tersekat, jadi anda boleh menggunakan pemeriksaan rawak, seperti Semak setiap 30 piksel Kod yang diubah suai adalah seperti berikut:
        Salin kod

        Kod XML/HTMLSalin kandungan ke papan keratan
        1. masa tamat = setTimeout(fungsi(){
        2. var imgData = ctx.getImageData(0,0,canvas.width,canvas.height);
        3. var dd = 0;
        4. untuk(var
        5. x=0;x<imgData.width;x =30){
        6. untuk(var
        7. y=0;y<imgData.height;y =30){
        8. var
        9. i = (y*imgData.width x)*4
        10. if(imgData.data[i 3]
        11. >0){
        12. dd dd
        13.                                                                 
        14.                                                               
        15. }
        16. if(dd/(imgData.width*imgData.height/900)
        17. <
        18. 0.4
        19. ){ canvas.className
        20. =
        21. "noOp" }
        22. },100)
        23. Ini boleh menghalang pengguna daripada mengklik secara liar ke tahap yang paling besar Jika terdapat kaedah semakan lain yang lebih baik, sila berikan pendapat anda, terima kasih.

          Pada langkah ini, segala-galanya telah ditulis, dan kemudian tiba masanya untuk menguji Hasilnya masih terperangkap pada android, jadi saya terpaksa memikirkan cara lain Akhirnya, saya menemui atribut globalCompositeOperation Persekitaran lukisan. Nilai lalai sifat ini adalah atas sumber, iaitu, ia akan ditindih apabila anda melukis pada piksel sedia ada, tetapi terdapat juga sifat yang dipanggil destinasi-keluar imej sumber. Hanya bahagian imej sasaran di luar imej sumber akan dipaparkan dan imej sumber adalah lutsinar. Nampaknya sukar untuk difahami, tetapi sebenarnya, jika anda mengujinya sendiri, anda akan mendapati bahawa ia adalah sangat mudah, iaitu, apabila anda melukis berdasarkan piksel sedia ada, piksel yang sedia ada di kawasan yang anda lukis akan menjadi telus boleh tukar terus dengan tengok gambar Mudah faham:
          2015511164219714.jpg (553×390)

          Ilustrasi kesan atribut globalCompositeOperation.
          Dengan atribut ini, ia bermakna tidak perlu menggunakan klip, dan tidak perlu menggunakan sin atau cos untuk mengira kawasan keratan hanya menggunakan garis tebal, yang boleh mengurangkan kos pengiraan dikurangkan, dan panggilan ke API persekitaran lukisan dikurangkan Prestasinya dipertingkatkan, dan berjalan pada Android sepatutnya lebih lancar:


          Kod XML/HTMLSalin kandungan ke papan keratan
          1. //Mencapai kesan pemadaman dengan mengubah suai globalCompositeOperation
          2. fungsi tapClip(){
          3. var segera = "ontouchstart" dalam tetingkap?true:false,
          4.  tekan mula = segera?"touchstart":"mousedown", 
          5.  tapmove = cepat?"touchmove":"mousemove", 
          6. tapend = cepat?"touchend":"mouseup";
          7.  
          8. canvas.addEventListener(tapstart, function(e){
          9. clearTimeout(timeout)
          10. e.preventDefault();
          11.  
          12.  
          13. x1 = gegas?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
          14.  
          15. y1 = cepat?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
          16.  
          17.  
          18. ctx.lineCap = "bulat"; //Tetapkan kedua-dua hujung garisan sebagai lengkok
          19.  
          20. ctx.lineJoin = "bulat"; //Tetapkan garisan bertukar kepada lengkok
          21. ctx.lineWidth = a*2;
          22. ctx.globalCompositeOperation
          23. = "destination-out"  
          24. ctx.save();
          25. ctx.beginPath()
          26. ctx.arc(x1,y1,1,0,2*Math.PI);
          27. ctx.fill();
          28. ctx.restore();
          29.  
          30. canvas.addEventListener(tapmove, tapmoveHandler);
          31. canvas.addEventListener(tapend, function(){
          32. canvas.removeEventListener(tapmove, tapmoveHandler
          33.                                                        
          34.    
          35. masa tamat
          36. =
          37. setTimeout
          38. (fungsi(){
          39.              var imgData = ctx.getImageData(0,0,canvas.width,canvas.height,);   
          40.              var dd = 0;   
          41.              untuk(var x=0;x< 🎜>imgData.width;x =30){   
          42.                  untuk(var y=0;y<><> 🎜>imgData.height;y =30){   
          43.                       var i = (y*imgData.width   x)*4;   
          44.                     jika(imgData.data[i 3] > 0){   
          45.                          dd   
          46.                     }   
          47.                 }   
          48.             }   
          49.             if(dd/(imgData.width*imgData.height/900)<0.4){   ){   
          50.                 canvas.className = "noOp";   
          51.             }   
          52.        },100)   
          53.         });   
          54.         fungsi tapmoveHandler(e){   
          55.             e.preventDefault()   
          56.             x2 = gegas?e.targetTouches[0].pageX:e.clientX-canvas ;   
          57.             y2 = gegas?e.targetTouches[0].pageY:e.offsetY-canvas ;   
          58.                
          59.             ctx.save();   
          60.             ctx.moveTo(x1,y1);   
          61.              ctx.lineTo(x2,y2);   
          62.             ctx.stroke();   
          63.             ctx.restore()   
          64.                
          65.              x1 = x2;   
          66.              y1 = y2;   
          67.         }   
          68.     })   
          69. }   

            擦除那部分代码就这么一点,也就相当于画图功能,直接设置line后接设置line后接设置line条,只要事前把globalCompositeOperation设成destination-out,你所进行的一切绘制,都变成了擦除效果。鼠标滑动触发的事件里面代码也少了很多,绘图对象的调用次少也减了,性能提升大大滴。

            改好代码后就立即用自己的android机子测试了一下,果然如此,跟上一且,一个了一下,果然如此,跟上一且,更天少达到了客户要求的能玩的地步了。

            源码地址:https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Funny-demo/clip/clip.html

    Kenyataan:
    Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn