このエフェクトは最近のプロジェクトで使用されたばかりで、モバイル デバイス上で画像をスクラッチして別の画像を表示するものに似ています。レンダリングは次のとおりです:
デモは右をクリックしてください: デモ
これはインターネット上で非常に一般的ですが、最初はオンラインでデモを見つけて、彼の方法を適用したかっただけです。顧客の要求により、Android 上で特にスムーズである必要はなく、少なくともプレイ可能である必要がありますが、オンラインで見つけたデモはラグがあり、まったくプレイできませんでした。なので、自分でも書いてみたかっただけで、この記事は研究過程を記録するためのものです。
このスクレイピング効果でまず思い浮かぶのは、キャンバスAPIでピクセルをクリアできるclearRectメソッドですが、結局のところclearRectメソッドは領域四角形をクリアします。消しゴムは丸いものに慣れている人が多いので、クリッピング エリアの強力な機能であるクリップ メソッドを紹介します。使用方法は非常に簡単です:
- ctx.save()
- ctx.beginPath()
- ctx.arc(x2,y2,a,0,2*Math.PI);
- ctx.clip()
- ctx.clearRect(0,0,canvas.width,canvas.height);
- ctx.restore();
上記のコードは円形領域の消去を実現しています。つまり、最初に円形パスを実装し、次にこのパスをクリッピング領域として使用し、その後ピクセルをクリアします。注意すべき点は、最初に描画環境を保存し、ピクセルをクリアした後に描画環境をリセットする必要があることです。リセットしないと、今後の描画はそのクリッピング領域に制限されます。
消去効果ができたので、次はマウスの移動による消去効果を記述します。モバイル版も同様であるため、マウスを使用して、mousedown を touchstart、mousemove に置き換えます。 touchmove で、mouseup で touchend を実行すると、座標点の取得が e.clientX から e.targetTouches[0].pageX に変更されます。
マウスの動きの消去を実装するために、最初はマウスが動いたときにトリガーされるmousemoveイベントでマウスが位置する円形の領域を消去することを考えました。 書き出してみると、マウスが非常に速く動くと、消去された領域が消去されることがわかりました。領域は一貫性を失い、次のような効果が表示されます。これは明らかに私たちが望んでいる消しゴム効果ではありません。
すべての点が一貫性がないため、次に行うことはこれらの点を接続することです。描画機能を実装している場合は、lineTo を介して 2 つの点を直接接続してから描画できますが、消去効果はクリッピング領域です。閉じたパスが必要です。2 つの点を接続するだけでは、クリッピング エリアを形成できません。次に、計算メソッドを使用して、2 つの消去領域内の四角形の 4 つの終点座標を計算することを考えました。これは、下の図の赤い四角形です:
計算方法も非常に簡単です。2 つのクリッピング領域を結ぶ線の 2 つの端点の座標がわかり、必要な線の幅もわかるため、長方形の 4 つの端点の座標は次のようになります。見つけやすいので、以下のコードがあります:
XML/HTML コード内容をクリップボードにコピー
- var aasin = a*Math.sin(Math.atan((y2-y1)/(x2- x1)));
- var aacos = a*Math.cos(Math.atan((y2-y1)/(x2-x1)) )
- var x3 = x1 asin; var
- y3 = y1-acos; var x4
- = x1-asin; var y4 =
- y1 acos; var x5 = x2
- asin; var y5 = y2 -acos;
- var x6 = x2-asin; var
-
y6 = y2 acos;
x1,y1とx2,y2が2つの端点なので、4つの端点の座標が得られます。このように、クリッピング領域は円と四角形で構成され、コードは次のように構成されます:
XML/HTML コードコンテンツをクリップボードにコピー- var hastouch = "ontouchstart" in window?true:false,//モバイルデバイスの場合
- tapstart = hastouch?"touchstart":"mousedown",
- tapmove = hastouch?"touchmove":"mousemove",
- tapend = hastouch?"touchend":"mouseup";
- canvas.addEventListener(tapstart , function(e){
- e.preventDefault();
- x1 = hastouch?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
- y1 = hastouch?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
- // マウスの初回クリック時に円形領域を消去し、同時に最初の座標点を記録します
- ctx.save()
- ctx.beginPath()
- ctx.arc(x1,y1,a,0,2*Math.PI);
- ctx.clip()
- ctx.clearRect(0,0,canvas.width,canvas.height);
- ctx.restore();
- Canvas.addEventListener(tapmove, TapmoveHandler);
- Canvas.addEventListener(tapend, function(){
- Canvas.removeEventListener(tapmove, TapmoveHandler);
- });
- //このイベントはマウスが移動するとトリガーされます
- 関数 TapmoveHandler(e){
- e.preventDefault()
- x2 = hastouch?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
- y2 = hastouch?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
- //2 点間のクリッピング領域の 4 つの端点を取得します
- var aasin = a*Math.sin(Math.atan((y2-y1)/(x2-x1)) );
- var aacos = a*Math.cos(Math.atan((y2-y1)/(x2-x1)) )
- var x3 = x1 asin; var
- y3 = y1-acos; var x4
- = x1-asin; var y4 =
- y1 acos; var x5 = x2
- asin; var y5 = y2 -acos;
- var x6 = x2-asin; var
- y6 = y2 acos;
- // 線の連続性を確保するため、長方形の一端に円を描きます ctx.save() ctx.beginPath()
- ctx.arc(x2,y2,a,0,2*Math.PI);
- ctx.clip()
- ctx.clearRect(0,0,canvas.width,canvas.height);
- ctx.restore();
- // 長方形のクリッピング領域内のピクセルをクリアします
- ctx.save()
- ctx.beginPath()
- ctx.moveTo(x3,y3);
- ctx.lineTo(x5,y5);
- ctx.lineTo(x6,y6);
- ctx.lineTo(x4,y4);
- ctx.closePath(); ctx.clip()
- ctx.clearRect(0,0,canvas.width,canvas.height);
- ctx.restore();
- //最後の座標を記録します
- x1 = x2; y1
- = y2; } })
- このようにして、マウスの消去効果が得られますが、もう 1 つ達成すべき点があります。これは、ほとんどの消去の効果で、一定のピクセル数を消去すると、すべての画像コンテンツが自動的に表示されます。効果を実現するには imgData を使用します。コードは次のとおりです: コードをコピー
コンテンツをクリップボードにコピーvarimgData- = ctx.getImageData(0,0,canvas.width,canvas.身長); var dd =
- 0; for(var x= 0
- ;ximgData.width;x =1){ for(var y= 0
- ;yimgData.height;y =1){ var i = (y*imgData.width x)*4; if(imgData.data[i 3]
- > 0){ dd dd
- }
- }
- if(dd/(imgData.width*imgData.height) 0.4){
- canvas.className = "noOp"; }
-
imgDataを取得し、imgData内のピクセルを走査し、imgDataのデータ配列内のrgbaのアルファを解析、つまり透明度を解析する ピクセルを消去すると透明度が0になります。現在のキャンバス内の透明度がゼロでないピクセルの数と、透明度がゼロでないピクセルの割合が 40% 未満の場合は、60% を超えることになります。現在のキャンバス上の領域を消去すると、画像が自動的に表示されます。
ここで、mouseup イベントにピクセルをチェックするコードを入れていることに注意してください。これは、ユーザーがマウスを乱暴にクリックすると、mouseup イベントが乱暴にトリガーされ、狂ってしまうことを意味するためです。ピクセルを計算するためにそのループをトリガーすると、計算量が多すぎるためプロセスがブロックされ、インターフェイスがスタックしてしまいます。解決策は次のとおりです。タイムアウトを追加してピクセル計算の実行を遅らせ、毎回タイムアウトをクリアします。ユーザーがクリックした時間、つまりユーザーが長時間クリックした場合、この計算はトリガーされなくなります。上で書いた方法は、ピクセルごとにチェックすることです。ピクセル数が大きすぎると確実にスタックしてしまうので、30 ピクセルごとにチェックするなどのランダム検査を使用できます。 修正されたコードは次のとおりです:
コードをコピーXML/HTML コードコンテンツをクリップボードにコピー- タイムアウト = setTimeout(function(){
- var imgData = ctx.getImageData(0,0,canvas.width,canvas.height);
- var dd = 0; for(var
- x=0;ximgData.width;x =30){ for(var
- y=0;yimgData.height;y =30){ var
- i = (y*imgData.width x)*4; if(imgData.data[i 3] >
- 0){ dd dd
- }
- if(dd/(imgData.width*imgData.height/900) 0.4){
- canvas.className = "noOp"
- ; } },100)
-
これにより、ユーザーが乱暴にクリックすることを最大限に防ぐことができます。他にもっと良いチェック方法がある場合は、ご意見をお聞かせください。
このステップではすべてが書かれていましたが、結果はまだ楽観的ではなかったので、最終的に、globalCompositeOperation 属性を見つけました。このプロパティのデフォルト値は、source-over です。つまり、既存のピクセルに描画するときにオーバーレイされますが、destination-out と呼ばれるプロパティもあります。正式な説明は、次のとおりです。ソース画像。ソース イメージの外側のターゲット イメージの部分のみが表示され、ソース イメージは透明になります。理解するのが難しいように思えますが、実際に試してみると非常に簡単であることがわかります。つまり、既存のピクセルに基づいて描画すると、描画した領域内の既存のピクセルが透明になります。画像を見て直接変更できます:
globalCompositeOperation 属性の効果の図。
この属性を使用すると、クリップを使用する必要がなくなり、クリッピング領域を計算するために sin や cos を使用する必要がなくなり、コストが大幅に削減されます。計算が削減され、描画環境 API の呼び出しが削減され、パフォーマンスが向上し、Android での実行がよりスムーズになるはずです。 以下は、変更されたコードです:XML/HTML コードコンテンツをクリップボードにコピー- //globalCompositeOperation を変更して消去効果を実現
- 関数 TapClip(){
- var hastouch = "ontouchstart" in window?true:false,
- tapstart = hastouch?"touchstart":"mousedown",
- tapmove = hastouch?"touchmove":"mousemove",
- tapend = hastouch?"touchend":"mouseup";
- Canvas.addEventListener(tapstart, function(e){
- clearTimeout(タイムアウト)
- e.preventDefault();
- x1 = hastouch?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
- y1 = hastouch?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
- ctx.lineCap = "round" // 線の両端を円弧として設定します ; >
- ctx.lineJoin = "round" // 円弧に曲がる線を設定します
- ctx.lineWidth = a*2; ctx.globalCompositeOperation
- = "宛先出力"; ctx.save();
- ctx.beginPath()
- ctx.arc(x1,y1,1,0,2*Math.PI);
- ctx.fill();
- ctx.restore();
- Canvas.addEventListener(tapmove, TapmoveHandler);
- Canvas.addEventListener(tapend, function(){
- Canvas.removeEventListener(tapmove, TapmoveHandler);
- timeout =
- setTimeout (function(){
- var imgData = ctx.getImageData(0,0,canvas.width,canvas.height);
- var dd = 0;
- for(var x=0;ximgData.width;x =30){
- for(var y=0;yimgData.height;y =30){
- var i = (y*imgData.width x)*4;
- if(imgData.data[i 3] > 0){
- dd
- }
- }
- }
- if(dd/(imgData.width*imgData.height/900)0.4){
- canvas.className = "noOp";
- }
- },100)
- });
- function tapmoveHandler(e){
- e.preventDefault()
- x2 = hastouch?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft ;
- y2 = hastouch?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop ;
- ctx.save();
- ctx.moveTo(x1,y1);
- ctx.lineTo(x2,y2);
- ctx.ストローク();
- ctx.restore()
- x1 = x2;
- y1 = y2;
- }
- })
- }
擦除那部分代码就这么一点,也就相当画图機能,直接設定line属性後通過lineTo行绘制線上条,只要事前操作globalCompositeOperation设在destination-out,你所行的一切绘制,都变成マウススライドのイベントフィールドコードも大幅に削減され、オブジェクトの使用回数も削減され、計算も削減され、パフォーマンスが大幅に向上しました。
コードを変更した後、すぐに自分の Android マシンがテストを行った結果、このように、相対的に多くのストリームが送信され、少なくとも顧客の要求に応じた機能が実現されました。出典地址:
https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Funny-demo/clip/clip.html

html5的div元素默认一行不可以放两个。div是一个块级元素,一个元素会独占一行,两个div默认无法在同一行显示;但可以通过给div元素添加“display:inline;”样式,将其转为行内元素,就可以实现多个div在同一行显示了。

html5中列表和表格的区别:1、表格主要是用于显示数据的,而列表主要是用于给数据进行布局;2、表格是使用table标签配合tr、td、th等标签进行定义的,列表是利用li标签配合ol、ul等标签进行定义的。

固定方法:1、使用header标签定义文档头部内容,并添加“position:fixed;top:0;”样式让其固定不动;2、使用footer标签定义尾部内容,并添加“position: fixed;bottom: 0;”样式让其固定不动。

HTML5中画布标签是“<canvas>”。canvas标签用于图形的绘制,它只是一个矩形的图形容器,绘制图形必须通过脚本(通常是JavaScript)来完成;开发者可利用多种js方法来在canvas中绘制路径、盒、圆、字符以及添加图像等。

html5中不支持的标签有:1、acronym,用于定义首字母缩写,可用abbr替代;2、basefont,可利用css样式替代;3、applet,可用object替代;4、dir,定义目录列表,可用ul替代;5、big,定义大号文本等等。

html5废弃了dir列表标签。dir标签被用来定义目录列表,一般和li标签配合使用,在dir标签对中通过li标签来设置列表项,语法“<dir><li>列表项值</li>...</dir>”。HTML5已经不支持dir,可使用ul标签取代。

html5是指超文本标记语言(HTML)的第五次重大修改,即第5代HTML。HTML5是Web中核心语言HTML的规范,用户使用任何手段进行网页浏览时看到的内容原本都是HTML格式的,在浏览器中通过一些技术处理将其转换成为了可识别的信息。HTML5由不同的技术构成,其在互联网中得到了非常广泛的应用,提供更多增强网络应用的标准机。

因为html5不基于SGML(标准通用置标语言),不需要对DTD进行引用,但是需要doctype来规范浏览器的行为,也即按照正常的方式来运行,因此html5只需要写doctype即可。“!DOCTYPE”是一种标准通用标记语言的文档类型声明,用于告诉浏览器编写页面所用的标记的版本。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。
