ホームページ > 記事 > WeChat アプレット > 小さなプログラム キャンバスを使用して、簡単な画像アプリケーションを作成します。
#小規模プログラム開発チュートリアルこのコラムでは、キャンバスを使用して絵を書く方法を紹介します
推奨事項 (無料): ミニプログラム開発チュートリアル
##アプリケーションの表示スクリーンショット
要件これは小さなアプリケーションなので、最終製品には
が適用されることを願っています。シナリオそして、それは 貴重な需要の源です
このアプリケーション要件のインスピレーション
これまでの仕事生活では、 # 同僚からうっかり ##美写真
現時点では、この写真を絵文字パックにしたいと考えています#通常、写真にいくつかのキャプションを追加します
興味深いコミュニケーション ツール (絵文字パッケージ) は、
要件分析を完了しました。
上記の要件の解体に基づいて、
ユーザーは画像をアップロードする必要があります
githubwarehouse https://github.com/luosijie/f.. .
私のプロジェクトが気に入ったら、励ましのスターを付けてください。見てみましょうこのアプリケーションはミニ プログラムを使用して開発されています
使用フレームワーク: mpx
テクノロジーの使用: ミニ プログラム キャンバス
import { createStore } from '@mpxjs/core' const store = createStore({ state: { cavas: null, // cnavas实例 ctx: null, // canvas上下文实例 elements: [], // canvas元素 activeIndex: null, // 当前编辑中的元素索引 mode: 'background', // 当前编辑模式:background, text, sticker fontStyle: { // 文字默认样式 opacity: 1, fillStyle: '#000000', strokeStyle: '#000000' } }, mutations: { setCanvas (state, data) { state.canvas = data }, setCtx (state, data) { state.ctx = data }, setElements (state, data) { state.elements = data }, setMode (state, data) { state.mode = data }, setActiveIndex (state, data) { state.activeIndex = data }, setFontStyle (state, { key, data }) { state.fontStyle[key] = data }, // 添加文字 addText (state) { const size = 50 const string = '请输入文字' const text = { type: 'text', data: string, scale: 1, size, left: 100, top: 100, rotate: 0, opacity: state.fontStyle.opacity, fillStyle: state.fontStyle.fillStyle, strokeStyle: state.fontStyle.strokeStyle } state.elements.push(text) state.activeIndex = state.elements.length - 1 }, // 添加贴图 addSticker (state, data) { state.elements.push(data) state.activeIndex = state.elements.length - 1 }, // 删除当前选中 deleteActiveELement (state) { state.elements.splice(state.activeIndex, 1) state.activeIndex = null }, // 清空画布 clear (state) { state.elements = [] state.activeIndex = null } } }) export default store
キャンバスの初期化
// 初始化画布 async initCanvas() { const query = this.createSelectorQuery() query .select('#canvas') .fields({ node: true, size: true }) .exec(async res => { const canvas = res[0].node const ctx = canvas.getContext('2d') store.commit('setCanvas', canvas) store.commit('setCtx', ctx) await this.loadImage('/images/icon-rotate.png').then(res => { this.image.rotate = res }) canvas.width = res[0].width * this.dpr canvas.height = res[0].height * this.dpr ctx.scale(this.dpr, this.dpr) this.drawGrid() }) }
絵の描画
/** * 绘制图片 * @param { Object } ele canvas元素 */ drawImage(ele) { this.ctx.save() const width = ele.width const height = ele.height const centerX = ele.left + ele.width / 2 const centerY = ele.top + ele.height / 2 this.ctx.translate(centerX, centerY) this.ctx.rotate(ele.rotate) this.ctx.drawImage(ele.data, ele.left - centerX, ele.top - centerY, width, height) this.ctx.restore() }
テキストの描画##/**
* 绘制文字
* @param { Object } ele canvas元素
*/
drawText(ele) {
this.ctx.save()
const width = ele.size * ele.data.length
const height = ele.size
const centerX = ele.left + width / 2
const centerY = ele.top + height / 2
this.ctx.translate(centerX, centerY)
this.ctx.rotate(ele.rotate)
this.ctx.font = `${ele.size}px bold sans-serif`
this.ctx.globalAlpha = ele.opacity
this.ctx.fillStyle = ele.fillStyle
this.ctx.strokeStyle = ele.strokeStyle
// this.ctx.lineWidth = 2
this.ctx.textBaseline = 'top'
console.log('draw-text', ele)
this.ctx.fillText(ele.data, ele.left - centerX, ele.top - centerY)
this.ctx.strokeText(ele.data, ele.left - centerX, ele.top - centerY)
this.ctx.restore()
}
initController(ele) {
const cs = this.convert2ControllerSize(ele)
this.ctx.save()
this.ctx.strokeStyle = '#eee'
this.ctx.translate(cs.centerX, cs.centerY)
this.ctx.rotate(cs.rotate)
// 绘制虚线边框
this.ctx.setLineDash([10, 5], 5)
this.ctx.strokeRect(cs.left - cs.centerX, cs.top - cs.centerY, cs.width, cs.height)
// 绘制控制点-旋转
this.ctx.drawImage(this.image.rotate, cs.left + cs.width - 10 - cs.centerX, cs.top + cs.height - 10 - cs.centerY, 20, 20)
this.ctx.restore()
}
// 画布渲染函数
renderCanvas() {
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height)
this.drawGrid()
console.log('draw-background', this.background)
if (this.background) this.drawImage(this.background)
for (let i = 0; i
移動
// 移动事件绑定函数
handleMove(e) {
console.log('mouse-move', e)
if (e.touches.length > 1) return
const x = e.touches[0].x
const y = e.touches[0].y
const dx = this.startTouches[0].x - x
const dy = this.startTouches[0].y - y
const elements = this.elements.slice()
elements[this.activeIndex || 0].left = this.startSelected.left - dx
elements[this.activeIndex || 0].top = this.startSelected.top - dy
store.commit('setElements', elements)
}
回転
// 旋转绑定函数 handleRotate(e) { console.log('handleRotate') const start = this.startTouches[0] const end = e.touches[0] const center = { x: this.startSelected.centerX, y: this.startSelected.centerY } const startLength = Math.sqrt((center.x - start.x) ** 2 + (center.y - start.y) ** 2) const endLength = Math.sqrt((center.x - end.x) ** 2 + (center.y - end.y) ** 2) const radian = this.convert2Radian(start, end, center) const scale = endLength / startLength const elements = this.elements.slice() const selected = elements[this.activeIndex] // 旋转 selected.rotate = this.startSelected.rotate - radian // 缩放 if (selected.type === 'text') { selected.left = this.startSelected.centerX - this.startSelected.size * this.startSelected.data.length * scale / 2 selected.top = this.startSelected.centerY - this.startSelected.size * scale / 2 selected.size = this.startSelected.size * scale } if (selected.type === 'sticker') { selected.left = this.startSelected.centerX - this.startSelected.width * scale / 2 selected.top = this.startSelected.centerY - this.startSelected.height * scale / 2 selected.width = this.startSelected.width * scale selected.height = this.startSelected.height * scale } store.commit('setElements', elements) }
Zoom // 缩放事件绑定函数
handleScale(e) {
if (e.touches.length !== 2 || this.mode !== 'background') return
const startLength = Math.sqrt(
(this.startTouches[0].x - this.startTouches[1].x) ** 2 +
(this.startTouches[0].y - this.startTouches[1].y) ** 2
)
const endLength = Math.sqrt(
(e.touches[0].x - e.touches[1].x) ** 2 + (e.touches[0].y - e.touches[1].y) ** 2
)
const scale = endLength / startLength
const elements = this.elements.slice()
const selected = elements[this.activeIndex || 0]
selected.left = this.startSelected.centerX - this.startSelected.width * scale / 2
selected.top = this.startSelected.centerY - this.startSelected.height * scale / 2
selected.width = this.startSelected.width * scale
selected.height = this.startSelected.height * scale
// elements[this.activeIndex || 0].scale = this.startSelected.scale * scale
store.commit('setElements', elements)
}
画像のエクスポート
export() { if (!store.state.elements.length) { wx.showToast({ title: '加点东西再导出吧', icon: 'none' }) return } wx.showModal({ title: '提示', content: '图片将保存到手机相册', success(res) { if (res.confirm) { console.log('export-canvas', store.state.ctx) const canvas = store.state.canvas wx.canvasToTempFilePath({ x: 0, y: 0, width: canvas.width, height: canvas.height, canvas, complete(res) { if (res.errMsg === 'canvasToTempFilePath:ok') { wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success(res) { wx.showToast({ title: '图片保存成功', icon: 'none' }) } }) } } }) } } }) }
以上が小さなプログラム キャンバスを使用して、簡単な画像アプリケーションを作成します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。