实现思路如下:
-
通过fabric.js绘制多张图片,同理这一步也可以直接使用canvas绘制多张图片;
-
通过save()将
整个绘制的canvas的内容
转成base64数据,然后onload方法后对图片进行剪切操作;
-
分割的方法主要就是canvas的
putImageData
以下两个demo略有不同:
1、直接渲染canvas
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body {
text-align: center;
#mycanvas {
background-color: red;
border: 1px solid #000000;
img {
margin: 20px;
.box {
position: fixed;
top: 100px;
right: 0;
</style>
</head>
<h3>使用canvas实现切图的效果 <button type="button" onclick="save()">按钮</button></h3>
<div class="box" id="box">
<div class="mycanvas">
<canvas id="mycanvas" width="300" height="800"></canvas>
<script src="fabric.min.js"></script>
<script>
var mycanvas = new fabric.Canvas('mycanvas');
fabric.Image.fromURL('2.jpg', function(oImg) {
oImg.set('selectable', false);
mycanvas.add(oImg);
fabric.Image.fromURL('2.jpg', function(oImg) {
oImg.set('selectable', false);
oImg.set({
top: 300
mycanvas.add(oImg);
mycanvas.setAttribute('height', 200)
function save() {
mycanvas.setBackgroundColor("blue");
const base64 = mycanvas.toDataURL({
format: 'jpeg',
quality: 1,
console.log(base64)
var imgToCut = new Image();
imgToCut.src = base64;
imgToCut.onload = function() {
cutImage(this);
function cutImage(img) {
var h = img.height,
w = img.width;
//创建Canvas
var oCanvas = createCanvas(w, h);
//拿到canvas的ctx
var ctx = oCanvas.getContext('2d');
//先drawImage,然后getImageData
ctx.drawImage(img, 0, 0, w, h);
var imageData = ctx.getImageData(0, 0, w, h);
resolveCut(imageData, 0, 0, 300, 150);
resolveCut(imageData, 0, 150, 300, 150);
document.getElementById('box').removeChild(oCanvas);
function resolveCut(imgData, x, y, w, h) {
console.log(x, y, w, h);
var cvs = createCanvas(w, h);
var ctx = cvs.getContext("2d");
ctx.putImageData(imgData, -x, -y);
function createCanvas(w, h) {
var canvas = document.createElement('canvas');
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
document.getElementById('box').appendChild(canvas);
return canvas;
</script>
</body>
</html>
2、先拿到canvas的base64,然后渲染成图片
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body {
text-align: center;
#mycanvas {
background-color: red;
border: 1px solid #000000;
img {
margin: 0;
display: block;
.box {
position: fixed;
top: 100px;
right: 0;
</style>
</head>
<h3>使用canvas实现九宫格切图的效果 <button type="button" onclick="save()">按钮</button></h3>
<div class="box" id="box">
<div class="mycanvas">
<canvas id="mycanvas" width="300" height="800"></canvas>
<script src="fabric.min.js"></script>
<script>
var mycanvas = new fabric.Canvas('mycanvas');
fabric.Image.fromURL('2.jpg', function(oImg) {
oImg.set('selectable', false);
mycanvas.add(oImg);
fabric.Image.fromURL('2.jpg', function(oImg) {
oImg.set('selectable', false);
oImg.set({
top: 300
mycanvas.add(oImg);
function save() {
mycanvas.setBackgroundColor("blue");
const base64 = mycanvas.toDataURL({
format: 'jpeg',
quality: 1,
console.log(base64)
var imgToCut = new Image();
imgToCut.src = base64;
imgToCut.onload = function() {
cutImage(this);
function cutImage(img) {
var h = img.height,
w = img.width;
//创建Canvas
var oCanvas = createCanvas(w, h);
//拿到canvas的ctx
var ctx = oCanvas.getContext('2d');
//先drawImage,然后getImageData
ctx.drawImage(img, 0, 0, w, h);
var imageData = ctx.getImageData(0, 0, w, h);
resolveCut(imageData, 0, 0, 300, 150);
resolveCut(imageData, 0, 150, 300, 150);
// document.getElementById('box').removeChild(oCanvas);
function resolveCut(imgData, x, y, w, h) {
console.log(x, y, w, h);
var cvs = createCanvas(w, h);
var ctx = cvs.getContext("2d");
ctx.putImageData(imgData, -x, -y);
var imgDom = document.createElement('img');
imgDom.setAttribute('src', cvs.toDataURL('image/jpeg')); // base 64
document.getElementById('box').appendChild(imgDom);
function createCanvas(w, h) {
var canvas = document.createElement('canvas');
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
// document.getElementById('box').appendChild(canvas);
return canvas;
</script>
</body>
</html>
实现思路如下:通过fabric.js绘制多张图片,同理这一步也可以直接使用canvas绘制多张图片; 通过save()将整个绘制的canvas的内容转成base64数据,然后onload方法后对图片进行剪切操作; 分割的方法主要就是canvas的putImageData以下为代码demo<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name="v
function createcanvas() {
var CANVAS=document.getElementById('mycanvas');
context=CANVAS.getContext('2d');
function drawImage() {
var img=new Image();
img.onload=function
const myCanvas = document.createElement('canvas');
myCanvas.width = 400;
myCanvas.height = 400;
const ctx = myCanvas.getContext('2d');
const img = new Image();
img.src = "1.jpg";
//当图片加载完毕的时候在drawImage,否则可能图片还没有加载完毕
img.onload=()=>{
ctx.drawImage(img, 0, 0, 100, 50)
canvas的toDataURL()方法是返回一个包含图片展示的 数据URL。可以使用type参数其类型,默认为PNG格式。图片的分辨率为96dpi。
canvas.toDataURL(type, encoderOptions);
1、type:图片格式,默认为 image/png,可以是其他image/jpeg等
2、encoderOptions:0到1之间的取值,主要用来选定图片的质量,默认值是0.92,超出范围也会选择默认值。
三、返回值
返回值是一个数据u...
参考链接 Fabric.js 简单介绍和使用简介
Fabric.js是一个可以简化canvas程序编写的库。 Fabric.js为canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的工具。基于MIT协议开源,在github上有许多人贡献代码。
为什么选择fabric.js
手上的项目必须使用canvas
原生的canvas API不够友好
用fabric.js实
fabric.toDataUrl 出现图片跨域问题背景解决思路
Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported
需要使用fabricjs 制作可以编辑配置的海报模板,但是在生成海报时 需要使用fabric.toDataUrl()来生成图片
没有成功,后来一查是...
1.1 业务场景
图片储存在后台中,根据图片的地址,在vue页面中,查看图片,并根据坐标标注指定区域。
由于浏览器的机制,使用 [removed].href 下载图片时,并不会保存到本地,会在浏览器打开。
2 实现原理
2.1 绘制画布
<el title=查看图片
visible.sync=dialogJPG
<canvas id=mycanvas width=940 height=570></canvas>
这里为了交互体验,使用了 element-ui 的
html5 canvas的简单类包装器(警告!Canvas当前仅在chrome中使用“ use strict”)
var id = 'myCanvas'; // id of canvas to which bind class
var c = new Canvas(id); // crate new instance for canvas to use
// Canvas is chainable function list (most of it's functions returns this)
c.rect({
x: 20,
y: 5,
w: 10,
h: 15
}).text({
text: 'Hello World',
x: 35,
y: 20,
type: 'stroke'
/* or
c.rect({x:
<canvas id=myCanvas width=200 height=100
style>
Your browser does not support the HTML5 canvas tag.
</canvas>
[removed]
var c=document.getElementById(my
<canvas id=myCanvas width=200 height=100
style>
Your browser does not support the HTML5 canvas tag.
</canvas>
[removed]
var c=document.getElementById(myCanvas);
现象:在使用canvas的toDataURL()方法时,控制台有时会报错:Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
原因:这是由于之前由drawImage()向canvas导入的图片跨域而导致的。
解决方法:...
目前只针对jpg/jpeg格式少部分测试,图片最终是以降低图片质量来限制图片大小,与原图差异较大,如果图片本身是以固定宽高(约150px * 150px)展示时,看不出来差异。
canvas针对png、gif图片的质量降低,处理后图片大小反而增加。不适用于png、gif格式图片
canvas转换成url前,需要已加载一张图片(称为原图),因此前后将保留两张图片的加载(了解)
代码仅处理了本...
<template>
<canvas canvas-id="myCanvas" style="width: 300px; height: 300px;"></canvas>
</template>
<script>
export default {
mounted() {
const ctx = uni.createCanvasContext('myCanvas', this);
// 加载图片
const image1 = uni.createImage();
image1.src = 'https://example.com/image1.png';
const image2 = uni.createImage();
image2.src = 'https://example.com/image2.png';
// 等待图片加载完成后绘制到画布上
Promise.all([loadImage(image1), loadImage(image2)])
.then(([img1, img2]) => {
// 绘制第一张图片
ctx.drawImage(img1, 0, 0, 300, 300);
// 绘制第二张图片,设置透明度为0.5
ctx.globalAlpha = 0.5;
ctx.drawImage(img2, 0, 0, 300, 300);
ctx.draw();
// 保存到相册
uni.canvasToTempFilePath({
canvasId: 'myCanvas',
success: function(res) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function() {
uni.showToast({
title: '保存成功',
icon: 'success'
fail: function() {
uni.showToast({
title: '保存失败',
icon: 'none'
}, this);
// 加载图片的函数
function loadImage(img) {
return new Promise((resolve, reject) => {
img.onload = () => resolve(img);
img.onerror = (err) => reject(err);
</script>
以上代码使用uniapp的canvas组件绘制了两张图片,并将第二张图片设置了透明度,使其叠加在第一张图片上。然后,使用uni.canvasToTempFilePath函数将画布转换为临时文件路径,再使用uni.saveImageToPhotosAlbum函数将该路径下的图片保存到相册中。保存成功后,使用uni.showToast函数提示用户。
coder李先生: