WeChatアプレットキャンバスが署名機能を実装

WeChatアプレットキャンバスが署名機能を実装

WeChatアプレットプロジェクトでは、開発モジュールに手書き署名機能が含まれ、WeChatアプレットキャンバスがデビューします

序文

WeChatアプレットキャンバスが署名機能を実装

コアコンテンツの紹介:

(1)署名の実施、開始、移動、終了

(2)書き直し

(3)完了

(4)アップロード

1. WeChatアプレットキャンバスが署名機能を実装

効果のデモンストレーション:

(1)署名の実施

(2)書き直し

(3)完了

完了したら、対応する位置に画像を表示します

(4)ビジネスニーズに応じて、背景に写真をアップロードし、必要な場所に表示することができます。

2. コード

1. すべてのデモ

wxml

<!--pages/canvas-test/canvas-test.wxml-->

<view class="handCenter">

 <canvas class="handWriting" disabled-scroll="true" bindtouchstart="uploadScaleStart" bindtouchmove="uploadScaleMove"
 bindtouchend="uploadScaleEnd" bindtap="mouseDown" canvas-id="handWriting">
 </キャンバス>

</ビュー>


<view class="handBtn">
 <button catchtap="retDraw" class="delBtn">書き換え</button>
 <button catchtap="subCanvas" class="subBtn">完了</button> 
</ビュー>


<view class="preview"> 

 <画像 wx:if="{{tmpPath}}" style="width:100%;height:100%;" src="{{tmpPath}}"></画像>

</ビュー>

js

const アプリ = getApp()
const api = require('../../utils/request.js'); //相対パス const apiEev = require('../../config/config');
ページ({
 データ: {
 キャンバス名: '手書き',
 ctx: ''、
 キャンバス幅: 0,
 キャンバスの高さ: 0,
 transparent: 1, // 透明度 selectColor: 'black',
 lineColor: '#1A1A1A', // 色 lineSize: 1.5, // 複数行に注意してください lineMin: 0.5, // 最小ストローク半径 lineMax: 4, // 最大ストローク半径 pressure: 1, // デフォルトの圧力 Smoothness: 60, // 滑らかさ、速度を計算するために 60 距離を使用します currentPoint: {},
 currentLine: [], // 現在の行 firstTouch: true, // 最初のトリガー radius: 1, // 円の半径 cutArea: { top: 0, right: 0, bottom: 0, left: 0 }, // 切り取り領域 bethelPoint: [], // すべての行によって生成されたベジェ点を保存します。
 最終ポイント: 0,
 chirography: [], //handwritingcurrentChirography: {}, //現在の手書きlinePrack: [], //線の軌跡、生成された線の実際のポイントtmpPath:''
 },
 // 手書き開始 uploadScaleStart (e) {
 if (e.type != 'touchstart') は false を返します。
 ctx = this.data.ctx; とします。
 ctx.setFillStyle(this.data.lineColor); // 初期の線の色の設定 ctx.setGlobalAlpha(this.data.transparent); // 半透明度の設定 let currentPoint = {
 x: e.touches[0].x、
 y: e.touches[0].y
 }
 currentLine を this.data.currentLine とします。
 現在の行をシフト解除({
 時間: 新しいDate().getTime()、
 否定: 0,
 x: 現在のポイント.x、
 y: 現在のポイント.y
 })
 this.setData({
 現在のポイント、
 // 現在の行
 })
 if (this.data.firstTouch) {
 this.setData({
 カットエリア: { 上: currentPoint.y、右: currentPoint.x、下: currentPoint.y、左: currentPoint.x },
 ファーストタッチ: 偽
 })
 }
 this.pointToLine(現在の行);
 },
 // 手書きの動き uploadScaleMove(e) {
 e.type != 'touchmove' の場合は false を返します。
 if (e.cancelable) {
 // デフォルトの動作が無効になっているかどうかを確認します if (!e.defaultPrevented) {
 e.preventDefault();
 }
 }
 ポイント = {
 x: e.touches[0].x、
 y: e.touches[0].y
 }

 //カットをテストする if (point.y < this.data.cutArea.top) {
 this.data.cutArea.top = point.y;
 }
 point.y < 0 の場合、this.data.cutArea.top = 0;

 (ポイントx>this.data.cutArea.right)の場合{
 this.data.cutArea.right = point.x;
 }
 if (this.data.canvasWidth - point.x <= 0) {
 this.data.cutArea.right = this.data.canvasWidth;
 }
 (ポイントy>this.data.cutArea.bottom)の場合{
 this.data.cutArea.bottom = point.y;
 }
 if (this.data.canvasHeight - point.y <= 0) {
 this.data.cutArea.bottom = this.data.canvasHeight;
 }
 (ポイントxがthis.data.cutArea.leftの場合){
 this.data.cutArea.left = point.x;
 }
 point.x < 0 の場合、this.data.cutArea.left = 0;

 this.setData({
 最後のポイント: this.data.currentPoint、
 currentPoint: ポイント
 })
 currentLine = this.data.currentLine とします。
 現在の行をシフト解除({
 時間: 新しいDate().getTime()、
 dis: this.distance(this.data.currentPoint, this.data.lastPoint),
 x: ポイント.x,
 y: ポイント.y
 })
 // this.setData({
 // 現在の行
 // })
 this.pointToLine(現在の行);
 },
 // 手書きが終わる uploadScaleEnd (e) {
 e.type != 'touchend' の場合、0 を返します。
 ポイント = {
 x: e.changedTouches[0].x、
 y: e.changedTouches[0].y
 }
 this.setData({
 最後のポイント: this.data.currentPoint、
 currentPoint: ポイント
 })
 currentLine = this.data.currentLine とします。
 現在の行をシフト解除({
 時間: 新しいDate().getTime()、
 dis: this.distance(this.data.currentPoint, this.data.lastPoint),
 x: ポイント.x,
 y: ポイント.y
 })
 // this.setData({
 // 現在の行
 // })
 (現在の行の長さ > 2) の場合 {
 var info = (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;
 //$("#info").text(info.toFixed(2));
 }
 // ストロークが完了したら、手書きの座標点を保存し、クリアして、現在の手書きが手書き領域内にあるかどうかを確認するチェックを追加します。
 this.pointToLine(現在の行);
 var 現在の書体 = {
 行サイズ: this.data.lineSize、
 線の色: this.data.lineColor
 };
 var chirography = this.data.chirography
 chirography.unshift(現在のCirography);
 this.setData({
 筆跡
 })
 var linePrack = this.data.linePrack
 linePrack.unshift(this.data.currentLine);
 this.setData({
 ラインプラック、
 現在の行: []
 })
 },
 オンロード(){
 キャンバス名を this.data.canvasName とします
 ctx = wx.createCanvasContext(キャンバス名) とします。
 this.setData({
 ctx: ctx
 })
 var クエリ = wx.createSelectorQuery();
 クエリ.select('.handCenter').boundingClientRect(rect => {
 this.setData({
 キャンバス幅: rect.width、
 キャンバスの高さ: rect.height
 })
 }).exec();
 },

 サブキャンバス(){
 // let that = this を追加します
 ctx = this.data.ctx; とします。
 ctx.draw(true,setTimeout(function(){ //新しいタイマーとコールバック wx.canvasToTempFilePath({
 x: 0,
 y: 0,
 幅: 375,
 高さ: 152,
 キャンバスID: '手書き',
 ファイルタイプ: 'png',
 成功: function(res) {
 that.setData({
 tmpPath:res.tempファイルパス
 })
 console.log(that.data.tmpPath,'それが何であるかを確認してください')
 that.upImgs(that.data.tmpPath,0)
 }
 }, ctx)
 },1000))
 },

// 保存した画像をファイルサーバーにアップロードするためのパスを追加します upImgs: function (imgurl, index) {
 console.log(imgurl,'パスを確認してください')
 var that = this;
 wx.uploadFile({
 url: apiEev.api + 'xxxx', //バックグラウンドアップロードパス filePath: imgurl,
 名前: 'ファイル',
 ヘッダー: {
 'コンテンツタイプ': 'マルチパート/フォームデータ'
 },
 フォームデータ: null、
 成功: 関数 (res) {
 console.log(res) //インターフェースはネットワークパスを返します var data = JSON.parse(res.data)
 console.log(data,'データが何であるかを確認します')
 if (data.code == "成功") {
 console.log('成功')
 }
 }
 })
},


 retDraw() {
 this.data.ctx.clearRect(0, 0, 700, 730)
 this.data.ctx.draw()
 this.setData({
 tmpPath:''
 })
 },
 

 // 2 つの点の間に線を描画します。パラメータは line で、最も近い 2 つの開始点を描画します。
 pointToLine (線) {
 this.calcBethelLine(行);
 戻る;
 },
 //補間方法を計算し、
 calcBethelLine (行) {
 (行の長さ<= 1)の場合{
 行[0].r = this.data.radius;
 戻る;
 }
 x0、x1、x2、y0、y1、y2、r0、r1、r2、len、lastRadius、dis = 0、time = 0、curveValue = 0.5 とします。
 行の長さが2以下の場合
 x0 = 行[1].x
 y0 = 行[1].y
 x2 = 線[1].x + (線[0].x - 線[1].x) * 曲線値;
 y2 = 線[1].y + (線[0].y - 線[1].y) * 曲線値;
 //x2 = 行[1].x;
 //y2 = 行[1].y;
 x1 = x0 + (x2 - x0) * 曲線値;
 y1 = y0 + (y2 - y0) * 曲線値;;

 } それ以外 {
 x0 = 線[2].x + (線[1].x - 線[2].x) * 曲線値;
 y0 = 線[2].y + (線[1].y - 線[2].y) * 曲線値;
 x1 = 行[1].x;
 y1 = 行[1].y;
 x2 = x1 + (line[0].x - x1) * 曲線値;
 y2 = y1 + (line[0].y - y1) * 曲線値;
 }
 // 計算式から、3 つの点は (x0, y0)、(x1, y1)、(x2, y2) です。(x1, y1) は制御点であり、曲線上には配置されません。実際、この点は手書きで取得した実際の点でもありますが、曲線上に配置されます。len = this.distance({ x: x2, y: y2 }, { x: x0, y: y0 });
 最後の半径 = this.data.radius;
 (n = 0; n < 行の長さ - 1; n++) の場合 {
 dis += 行[n].dis;
 時間 += 行[n].時間 - 行[n + 1].時間;
 if (dis > this.data.smoothness) break;
 }
 this.setData({
 半径: Math.min(time / len * this.data.pressure + this.data.lineMin, this.data.lineMax) * this.data.lineSize
 });
 行[0].r = this.data.radius;
 //手書きの半径を計算します。
 行の長さが2以下の場合
 r0 = (lastRadius + this.data.radius) / 2;
 r1 = r0;
 r2 = r1;
 //戻る;
 } それ以外 {
 r0 = (行[2].r + 行[1].r) / 2;
 r1 = 行[1].r;
 r2 = (行[1].r + 行[0].r) / 2;
 }
 n = 5 とします。
 ポイントを [] とします。
 (i = 0; i < n; i++ とします) {
 t = i / (n - 1)とします。
 x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2 とします。
 y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2 とします。
 r = lastRadius + (this.data.radius - lastRadius) / n * i とします。
 point.push({ x: x, y: y, r: r });
 ポイントの長さが3の場合
 a = this.ctaCalc(point[0].x, point[0].y, point[0].r, point[1].x, point[1].y, point[1].r, point[2].x, point[2].y, point[2].r);とします。
 a[0].color = this.data.lineColor;
 // bethelPoint を this.data.bethelPoint とします。
 // コンソール.log(a)
 // コンソールログ(this.data.bethelPoint)
 // bethelPoint = bethelPoint.push(a);
 描画する
 点 = [{ x: x, y: y, r: r }];
 }
 }
 this.setData({
 現在の行: 行
 })
 },
 // 2点間の距離を求める distance (a, b) {
 x = bx - ax とします。
 y = by - ayとします。
 Math.sqrt(x * x + y * y) を返します。
 },
 ctaCalc (x0, y0, r0, x1, y1, r1, x2, y2, r2) {
 a = [], vx01, vy01, norm, n_x0, n_y0, vx21, vy21, n_x2, n_y2とします。
 関数x1とx0の積。
 vy01 = y1 - y0;
 ノルム = Math.sqrt(vx01 * vx01 + vy01 * vy01 + 0.0001) * 2;
 vx01 = vx01 / ノルム * r0;
 vy01 = vy01 / ノルム * r0;
 0x0 ...
 y0 = -vx01; を出力します。
 vx21 = x1 - x2;
 vy21 = y1 - y2;
 ノルム = Math.sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001) * 2;
 vx21 = vx21 / ノルム * r2;
 vy21 = vy21 / ノルム * r2;
 関数 n_x2 = -vy21;
 y2 = vx21; のようになります。
 a.push({ mx: x0 + n_x0, my: y0 + n_y0, 色: "#1A1A1A" });
 a.push({ c1x: x1 + n_x0, c1y: y1 + n_y0, c2x: x1 + n_x2, c2y: y1 + n_y2, ex: x2 + n_x2, ey: y2 + n_y2 });
 a.push({ c1x: x2 + n_x2 - vx21, c1y: y2 + n_y2 - vy21, c2x: x2 - n_x2 - vx21, c2y: y2 - n_y2 - vy21, ex: x2 - n_x2, ey: y2 - n_y2 });
 a.push({ c1x: x1 - n_x2, c1y: y1 - n_y2, c2x: x1 - n_x0, c2y: y1 - n_y0, ex: x0 - n_x0, ey: y0 - n_y0 });
 a.push({ c1x: x0 - n_x0 - vx01, c1y: y0 - n_y0 - vy01, c2x: x0 + n_x0 - vx01, c2y: y0 + n_y0 - vy01, ex: x0 + n_x0, ey: y0 + n_y0 });
 1. 固定長のmxを0にする。
 文字列をparse(0)します。
 a[0].my = a[0].my.toFixed(1);
 a[0].my = parseFloat(a[0].my);
 (i = 1; i < a.length; i++ とします) {
 1. 固定長のc1xを固定長のc1xに変換する。
 パースフロート
 1. 固定長のc1yを出力します。
 a[i].c1y = parseFloat(a[i].c1y);
 1. 固定長のc2xをa[i]に代入する。
 パースフロート
 1. 固定長のc2yを出力します。
 python 4.0 では、 ...
 a[i].ex = a[i].ex.toFixed(1);
 パースフロート
 a[i].ey = a[i].ey.toFixed(1);
 a[i].ey = parseFloat(a[i].ey);
 }
 を返します。
 },
 bethelDraw (ポイント、is_fill、色) {
 // let that = this を追加します
 ctx = this.data.ctx; とします。
 ctx.beginPath();
 ctx.moveTo(ポイント[0].mx、ポイント[0].my);
 (未定義!=色)の場合{
 ctx.setFillStyle(色);
 ctx.setStrokeStyle(色);
 } それ以外 {
 ctx.setFillStyle(ポイント[0].color);
 ctx.setStrokeStyle(ポイント[0].color);
 }
 (i = 1 とします; i < point.length; i++) {
 ctx.bezierCurveTo(ポイント[i].c1x、ポイント[i].c1y、ポイント[i].c2x、ポイント[i].c2y、ポイント[i].ex、ポイント[i].ey);
 }
 ctx.stroke();
 (未定義!= is_fill)の場合{
 ctx.fill(); // グラフィックを塗りつぶします (後で描画したグラフィックは前のグラフィックを覆います。描画するときは順序に注意してください)
 }
 ctx.draw(true)
 },
 selectColorEvent (イベント) {
 console.log(イベント)
 var color = event.currentTarget.dataset.colorValue;
 var colorSelected = event.currentTarget.dataset.color;
 this.setData({
 選択色: 選択された色、
 線の色: 色
 })
 }
})
/* ページ/canvas-test2/canvas-test2.wxss */
.キャンバスID {
 位置: 絶対;
 左: 50%;
 上: 0;
 変換: 翻訳(-50%);
 zインデックス: 1;
 境界線: 2px 破線 #ccc;
 境界線の半径: 8px;
 下部マージン: 66px;
}

.handCenter{
 境界線: 1px 実線の赤;
}

.手書き{
 幅: 100%;
}

.プレビュー{
 幅: 375ピクセル;
 高さ: 152px;
}

2. 主要部品の分析

(1)署名、開始、移動、終了の基本実装

// 手書き開始 uploadScaleStart (e) {
 if (e.type != 'touchstart') は false を返します。
 ctx = this.data.ctx; とします。
 ctx.setFillStyle(this.data.lineColor); // 初期の線の色の設定 ctx.setGlobalAlpha(this.data.transparent); // 半透明度の設定 let currentPoint = {
 x: e.touches[0].x、
 y: e.touches[0].y
 }
 currentLine を this.data.currentLine とします。
 現在の行をシフト解除({
 時間: 新しいDate().getTime()、
 否定: 0,
 x: 現在のポイント.x、
 y: 現在のポイント.y
 })
 this.setData({
 現在のポイント、
 // 現在の行
 })
 if (this.data.firstTouch) {
 this.setData({
 カットエリア: { 上: currentPoint.y、右: currentPoint.x、下: currentPoint.y、左: currentPoint.x },
 ファーストタッチ: 偽
 })
 }
 this.pointToLine(現在の行);
 },
 // 手書きの動き uploadScaleMove(e) {
 e.type != 'touchmove' の場合は false を返します。
 if (e.cancelable) {
 // デフォルトの動作が無効になっているかどうかを確認します if (!e.defaultPrevented) {
 e.preventDefault();
 }
 }
 ポイント = {
 x: e.touches[0].x、
 y: e.touches[0].y
 }

 //カットをテストする if (point.y < this.data.cutArea.top) {
 this.data.cutArea.top = point.y;
 }
 point.y < 0 の場合、this.data.cutArea.top = 0;

 (ポイントx>this.data.cutArea.right)の場合{
 this.data.cutArea.right = point.x;
 }
 if (this.data.canvasWidth - point.x <= 0) {
 this.data.cutArea.right = this.data.canvasWidth;
 }
 (ポイントy>this.data.cutArea.bottom)の場合{
 this.data.cutArea.bottom = point.y;
 }
 if (this.data.canvasHeight - point.y <= 0) {
 this.data.cutArea.bottom = this.data.canvasHeight;
 }
 (ポイントxがthis.data.cutArea.leftの場合){
 this.data.cutArea.left = point.x;
 }
 point.x < 0 の場合、this.data.cutArea.left = 0;

 this.setData({
 最後のポイント: this.data.currentPoint、
 currentPoint: ポイント
 })
 currentLine = this.data.currentLine とします。
 現在の行をシフト解除({
 時間: 新しいDate().getTime()、
 dis: this.distance(this.data.currentPoint, this.data.lastPoint),
 x: ポイント.x,
 y: ポイント.y
 })
 // this.setData({
 // 現在の行
 // })
 this.pointToLine(現在の行);
 },
 // 手書きが終わる uploadScaleEnd (e) {
 e.type != 'touchend' の場合、0 を返します。
 ポイント = {
 x: e.changedTouches[0].x、
 y: e.changedTouches[0].y
 }
 this.setData({
 最後のポイント: this.data.currentPoint、
 currentPoint: ポイント
 })
 currentLine = this.data.currentLine とします。
 現在の行をシフト解除({
 時間: 新しいDate().getTime()、
 dis: this.distance(this.data.currentPoint, this.data.lastPoint),
 x: ポイント.x,
 y: ポイント.y
 })
 // this.setData({
 // 現在の行
 // })
 (現在の行の長さ > 2) の場合 {
 var info = (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;
 //$("#info").text(info.toFixed(2));
 }
 // ストロークが完了したら、手書きの座標点を保存し、クリアして、現在の手書きが手書き領域内にあるかどうかを確認するチェックを追加します。
 this.pointToLine(現在の行);
 var 現在の書体 = {
 行サイズ: this.data.lineSize、
 線の色: this.data.lineColor
 };
 var chirography = this.data.chirography
 chirography.unshift(現在のCirography);
 this.setData({
 筆跡
 })
 var linePrack = this.data.linePrack
 linePrack.unshift(this.data.currentLine);
 this.setData({
 ラインプラック、
 現在の行: []
 })
},

最初にonloadで初期化することを忘れないでください

コードを取得して直接使用する

(2)再署名

簡単に言えば、キャンバスをクリアすることを意味します。

retDraw() {
 this.data.ctx.clearRect(0, 0, 700, 730)
 this.data.ctx.draw()
 this.setData({
 tmpPath:''
 })
},

(3)署名完了

サブキャンバス(){
 // let that = this を追加します
 ctx = this.data.ctx; とします。
 ctx.draw(true,setTimeout(function(){ //新しいタイマーとコールバック wx.canvasToTempFilePath({
 x: 0,
 y: 0,
 幅: 375,
 高さ: 152,
 キャンバスID: '手書き',
 ファイルタイプ: 'png',
 成功: function(res) {
 that.setData({
 tmpPath:res.tempファイルパス
 })
 console.log(that.data.tmpPath,'それが何であるかを確認してください')
 that.upImgs(that.data.tmpPath,0)
 }
 }, ctx)
 },1000))
 },

内部のコールバックの方が重要です:

キャンバスのコンテンツが失われないように、遅延を設定できます。
wx.canvasToTempFilePath メソッドはキャンバス イメージのコンテンツを取得します。

(4)ビジネスニーズに応じて、背景に写真をアップロードし、必要な場所に表示することができます。

重要なのはバックグラウンドにアップロードする方法です

// 保存した画像をファイルサーバーにアップロードするためのパスを追加します upImgs: function (imgurl, index) {
 console.log(imgurl,'パスを確認してください')
 var that = this;
 wx.uploadFile({
 url: apiEev.api + 'xxxx', //バックグラウンドファイルアップロードパスインターフェース filePath: imgurl,
 名前: 'ファイル',
 ヘッダー: {
 'コンテンツタイプ': 'マルチパート/フォームデータ'
 },
 フォームデータ: null、
 成功: 関数 (res) {
 console.log(res) //インターフェースはネットワークパスを返します var data = JSON.parse(res.data)
 console.log(data,'データが何であるかを確認します')
 if (data.code == "成功") {
 console.log('成功')
 }
 }
 })
},

要約する

WeChat ミニプログラム キャンバスは署名機能を実装します。

特別な注意:実機デバッグおよび体験版では遅延が発生する可能性があります。可能であれば、プレリリース版にリリースして、パフォーマンスに影響があるかどうかを確認してください。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Uniapp が WeChat アプレットの電子署名効果を実装 (デモ付き)
  • WeChat アプレットに手書き署名を実装するためのサンプル コード
  • WeChatアプレットはシンプルな手書き署名コンポーネントを実装します
  • 電子署名を実装するWeChatミニプログラム
  • WeChatミニプログラムが電子署名機能を実装
  • WeChatアプレットは電子署名を実装し、画像をエクスポートします
  • Java が WeChat アプレット「支払い検証署名に失敗しました」問題に遭遇した解決策
  • .NET WeChat アプレットのユーザーデータ署名検証および復号化コード
  • WeChatアプレットが横画面と縦画面の署名機能を実装

<<:  Mysql 5.7.17 をインストールした後、MySQL にログインするチュートリアル

>>:  CentOS7 ファイアウォールとオープンポートの簡単な使い方の簡単な紹介

推薦する

階段効果を実現するためのWeChatアプレットカスタムメニューナビゲーション

設計意図ページを開発する際には、ページ上のナビゲーション メニューをクリックしたときにページを対応す...

Mysql sql スロークエリ監視スクリプトコード例

1. my.cnfを変更する #全体的な効果としては、グローバルがオンになっている場合はテーブルとロ...

MySQLは実際に分散ロックを実装できる

序文前回の記事では、eコマース シナリオでのフラッシュ セールの例を通じて、モノリシック アーキテク...

EDMをHTMLで記述する際の注意点まとめ(メール送信時の一般的な注意点)

フォーマットエンコーディング1. ページの幅は600~800px、長さは1024px以内に設定してく...

MySQL をベースにしたシンプルな検索エンジンを実装する

目次MySQL ベースの検索エンジンの実装1. ngram全文パーサー2. 全文インデックスを作成す...

MySQL 全文インデックスガイド

全文インデックスには特別なクエリ構文が必要です。全文検索はインデックスの有無にかかわらず実行できます...

nginxアクセス制御の実装例

高性能で軽量なウェブサービスソフトウェアであるNginxについて高い安定性 システムリソースの消費量...

HTML テーブル マークアップ チュートリアル (10): セル パディング属性 CELLPADDING

セルのパディングは、セルの内容と境界線の間の距離です。基本的な構文<TABLE セルパディング...

HTML リスト タグ dl、ul、ol の使用例

コードをコピーコードは次のとおりです。 <!--リストタグ: <dl>: 階層リス...

Vue.js ソースコード解析のカスタム手順の詳細な説明

序文コア機能のデフォルトの組み込みディレクティブ (v-model および v-show) に加えて...

アダプティブ Web デザインの手法 (モバイル フォンでの優れたアクセス エクスペリエンス)

1. HTML ヘッダーにビューポート タグを追加します。ウェブサイトの HTML ファイルの先頭...

Ubuntuのインストール Matlab2020b の詳細なチュートリアルとリソース

目次1. リソースファイル2. インストール2.1 詳細な手順2.1.1 ディスクイメージのマウント...

強くお勧めします! Vue 3.2 でシンタックスシュガーを設定する

目次前の1. セットアップ構文シュガーとは何か2. セットアップコンポーネントを使用して自動的に登録...

HTML に FLASH へのリンクを追加し、すべての主要ブラウザと互換性を持たせる方法

まずコードを見てみましょうコードをコピーコードは次のとおりです。 <div style=&qu...

HTML テーブルタグチュートリアル (12): 境界線スタイル属性 FRAME

FRAME プロパティを使用して、表の境界線のスタイル タイプを制御します。基本的な構文<T...