H 5 canvas画像を生成し、アップロードファイルをPDFに転送してcanvas文字レイアウトをダウンロードする
8139 ワード
最近、小さなプログラム側でプレビュー機能をカスタマイズし、プレビューした画像に指定した外部フォントを使用するビジネスニーズに遭遇しました.プレビューした画像をOSSにアップロードし、バックエンドにPDFを生成し、管理システムでダウンロードします.しかし............、実践の発見を経て、小さいプログラムはパケット処理をしたにもかかわらず、依然としてローカルにフォントパケットを保存することができなくて、フォントをOSSの上で戻すことができなくて、しかしドメインをまたいで現れて、ドメインをまたいで許可することを配置したにもかかわらず、依然としてだめです.しかも!!!ウィジェットの
技術的要点 canvas文字レイアウト canvas設定指定背景色 canvas外部フォント を導入 canvas描画文字画像 canvasによって生成されたbase 64ピクチャをfileアップロード(ここではバックエンド交渉、ここではバックエンド要求) に変換する.画像をPDFに生成し、一括ダウンロード をクリックします.
実装手順
canvas文字レイアウト
一般的な
テキストが自動改行を超えた場合、デフォルトのテキストがコンテナ幅を超えた場合に自動的に改行されます.また、テキストコンテナに
具体的な効果は以下の通りです.
しかし、これはブラウザにも一定の互換性の問題があり、使用する際に注意が必要です. 各行の幅を1文字サイズに設定し、テキストがデフォルトの改行を超えたプロパティを使用するか、強制改行を超えたテキストの縦組みを設定します. .
文字ごとに文字横並び を実現する.文字縦 を実現する.
縦並びの論理は横並びと同じです.文字縦列は
部分コードクリップ
canvas背景色の設定
しかし、背景と文字の描画順序に注意してください.
canvas外部フォントの導入
1.まずフォントライブラリを導入します.ローカルスペースを節約するために、サービス側から導入できますが、ドメイン間の問題に注意する必要があります.また、フォントライブラリをローカルに配置し、直接パスに対して導入することもできます.
2.
canvasテキストピクチャの描画
canvasは画像を生成し、サービス側をアップロードします.
サービス側が
ここで注意してください.
画像をPDFに生成し、一括ダウンロードをクリックします.
ここではバックエンドと相談して、
canvas API
はフォントを設定できず、h 5のcanvasのcontext.font = ' '
の方法はありません.最終的に曲線救国を決定し、小プログラム端のプレビュー生成canvas機能を放棄し、canvasをフォントに導入し、画像を生成するなどの操作を管理システムに置き、原生canvas
を採用して実現した.技術的要点
実装手順
canvas文字レイアウト
一般的な
HTML
コンテナでは、文字のレイアウトを実現するには簡単です.例:テキストが自動改行を超えた場合、デフォルトのテキストがコンテナ幅を超えた場合に自動的に改行されます.また、
word-wrap:break-word
を使用して強制改行を行うこともできます.文字の縦組みを実現するには、いくつかの方法があります.writing-mode
のスタイルを設定する:(互換性の問題がある)writing-mode:vertical-rl;// 。 top-bottom-right-left
writing-mode:vertical-lr;// ,
具体的な効果は以下の通りです.
しかし、これはブラウザにも一定の互換性の問題があり、使用する際に注意が必要です.
を使用して改行を制御する:(互換性がない、推奨方式)br
タグ実装または文字ごとに1つのタグを格納改行:(堅苦しい書き方、比較low、推奨しない)文字ごとに
br
のラベルを追加したり、文字ごとにラベルを1つ置いたりすると、書く柔軟性が高くなく、とてもお勧めできません.canvas
での文字レイアウトの実装canvas
では、テキストがcanvas
サイズを超えていて、自動的に改行されない場合は、超えた後に直接一列に描画されます.canvas
にも改行を直接設定できるapiはありませんが、どのように改行を実現すればいいのでしょうか.js
によって制御することができ、現在の描画文字のx
座標を計算することによって、x座標がcanvas
の幅より大きい場合、x
座標を0
(描画の開始点x座標)に割り当て、y
座標は1文字の高さを加算し、テキストの改行を実現する.縦並びの論理は横並びと同じです.文字縦列は
y
座標が累加されただけで、canvas
の高さを超えた場合、y
座標を0
(描画の開始点y座標)に割り当て、x
座標を1文字の高さに累加して縦列かつテキストの改行を実現する.部分コードクリップ
/**
* canvas
* @param {CanvasRenderingContext2D } context
* @param { } text
* @param { x } x
* @param { y } y
*/
drawTextVertical(context, text, x, y) {
let startX = x,
startY = y; // ,
let spaceCount = 0;
let arrText = text.trim().split('');
let formatText = text.replace(/\//g, '').split(''); //
let align = context.textAlign;
let baseline = context.textBaseline;
context.textAlign = 'center';
context.textBaseline = 'middle';
context.font = 'Pacifico'
//
arrText.forEach(function (letter, index) {
//
//
let code = letter.charCodeAt(0);
//
let letterWidth = 22 * 2.3;
if (code <= 256) {
context.translate(x, y);
// , 90°
context.rotate(90 * Math.PI / 180);
context.translate(-x, -y);
}
if (code !== 47) context.fillText(letter, x, y);
//
context.setTransform(1, 0, 0, 1, 0, 0);
// 8 9
if ((code === 47 && !spaceCount) || (!spaceCount && index && index % 7 === 0)) {
// / charCode=47
spaceCount += 1;
y = startY;
x = index ? (startX + letterWidth) : x;
startX = x;
} else if (code !== 47) {
//
if (code !== 32) {
y = y + letterWidth;
} else {
y = y + letterWidth / 2
}
}
});
//
context.textAlign = align;
context.textBaseline = baseline;
}
canvas背景色の設定
canvas
ピクチャを生成する場合はピクチャフォーマット(jpg,jpeg,pngなど)を指定できますが、
(大会歪み)のみ生成できます.canvas
生成ピクチャの品質を向上させるにはhidpi-canvas-polyfillプラグインを導入し、具体的にはこの記事を参照してcanvas生成ピクチャのぼかしを解決することができます.canvas
生成ピクチャの背景はデフォルトでは透明であり、背景色を個別に設定したい場合はctx.fillStyle
を使用して塗りつぶすことができますが、文字色を設定すると、文字色もctx.fillStyle
を使用するため、背景色が上書きされます.では、この場合は以下の方法で解決することができる:1.canvas.getImageData
を用いるキャンバス上の画素データ2を複製する.複製する各画素点を巡回し、各画素にrgb
の値3を設定.設定されたストリームデータをputImageData
を介してキャンバスに戻します. let imageData = ctx.getImageData(0, 0, width, height);
for (let i = 0; i < imageData.data.length; i += 4) {
// ,
if (imageData.data[i + 3] == 0) {
imageData.data[i] = 255;
imageData.data[i + 1] = 255;
imageData.data[i + 2] = 255;
imageData.data[i + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
しかし、背景と文字の描画順序に注意してください.
,
です.順序が逆になると、文字は明らかに鋸歯状になり、少しぼやけてしまいます.これは、位置決め中のz-index
と原理が似ています.canvas外部フォントの導入
1.まずフォントライブラリを導入します.ローカルスペースを節約するために、サービス側から導入できますが、ドメイン間の問題に注意する必要があります.また、フォントライブラリをローカルに配置し、直接パスに対して導入することもできます.
//
@font-face {
font-family: "FZCUJINLJW";
src: url('https://www.xxxx.com/FZCUJINLJW.TTF') ;
}
//
@font-face {
font-family: "FZCUJINLJW";
src: url('../../assets/FZCUJINLJW.TTF') ;
}
2.
CanvasRenderingContext2D
オブジェクトによりフォント、文字等を設定するctx.font = '24px FZCUJINLJW';
ctx.fillStyle = '#db9a00';//
canvasテキストピクチャの描画
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');// CanvasRenderingContext2D
ctx.beginPath();//
ctx.font = `${FONT_SIZE}px FZCUJINLJW`;
ctx.fillStyle = '#db9a00';//
ctx.fillText(' ', /* x */, /* y */);
let imgBase64 = canvas.toDataURL('image/png', 1);
ctx.closePath();
ctx.save();//
// , , , 。
ctx.clearRect(0, 0, canvasObj.width, canvasObj.height);
canvasは画像を生成し、サービス側をアップロードします.
ctx.toDataURL
によりキャンバスコンテンツのbase64
を取得できるlet imgBase64 = canvas.toDataURL('image/png', 1);
サービス側が
base64
を使用してアップロードをサポートしている場合は、処理は必要ありません.ここでは、バックエンドにfileファイルタイプが必要であるため、base64
をfile
に変換する必要があります.コードは以下のとおりです.let file = dataURLtoFile(imgBase64, 'jpg'); // base file
function dataURLtoFile(urlData, fileName) {
var bytes = window.atob(urlData.split(',')[1]); // url , byte
var mime = urlData.split(',')[0].match(/:(.*?);/)[1];
// , ascii 0 0
var ab = new ArrayBuffer(bytes.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new File([ab], fileName, { type: mime });
}
file
に変換後、FormData
形式でアップロードlet formdata = new FormData();
formdata.append('multipartList', file);
ajax.post(url,data:formdata).then()
ここで注意してください.
canvas
で生成された画像が比較的小さい場合(例えば5 kb以下)、ファイルのアップロードに失敗する可能性があります.私は前にこの穴を踏んだことがあります.画像をPDFに生成し、一括ダウンロードをクリックします.
ここではバックエンドと相談して、
canvas
で生成したピクチャをサービス側にアップロードし、ピクチャのOSS
アドレスに戻り、このアドレスをパラメータとしてバックエンドに伝え、PDF
のダウンロードリンクを取得し、フロントエンドはwindow.open(url)
でファイルダウンロードを実現する.let uploadUrl = window.interfercesPrefix + '/admin/goods/tbgoods/uploadImages';
let downLoadUrl = '/app/goods/tbgoods/downLoadPdf';
//
ajaxUploderImg({ url: uploadUrl, data: formdata }).then(res => {
// PDF
this.props.dispatch(downLoadPdf({ url: downLoadUrl, imgUrl: res.data }));
}).catch(err => {
if (err) {
notification['error']({
message: err.message,
description:
' , !',
});
} else {
notification['error']({
message: ' , '
});
}
})