javascript - 无法下载带有过滤器的画布图像
问题描述
我有一个页面,用户可以在其中放置一些过滤器,例如hue-rotate, blur, invert, saturate and sepia
. 之后,他们可以通过按保存图片按钮来下载它。问题是图片下载但没有任何过滤器。我使用画布并添加过滤器CanvasRenderingContext2D.filter
。当我检查时,console.log()
我ctx.filter
接受了一些过滤器。当按下保存图片按钮时,我尝试使用drawImage()
功能重绘文件,它使用过滤器下载,但这是另一个问题,即使过滤器重置,用户放在页面上的当前 img 也会变成过滤器。我的意思是图片似乎用户已经在页面上下载了带有过滤器的图片。有什么建议么?以下代码和页面图片:
window.addEventListener("DOMContentLoaded", () => {
const filters = document.querySelectorAll(".filters input"),
btnReset = document.querySelector(".btn.btn-reset"),
btns = document.querySelectorAll(".btn-container .btn"),
btnContainer = document.querySelector(".btn-container"),
btnLoadPicture = document.querySelector(".btn.btn-load #btnInput");
const canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
saveBtn = document.querySelector(".btn.btn-save");
const img = new Image();
// filter change
function handleUpdate() {
const suffix = this.dataset.sizing || "";
document.documentElement.style.setProperty(
`--${this.name}`,
this.value + suffix
);
this.nextElementSibling.value = this.value;
filterDownload();
}
function filterDownload() {
let hold = "";
for (let i = 0; i < filters.length; i++) {
hold =
hold +
filters[i].name +
"(" +
filters[i].value +
filters[i].dataset.sizing +
")";
}
ctx.filter = hold;
console.log(ctx);
}
// load button function
canvas.dataMaxWidth = canvas.width;
canvas.dataMaxHeight = canvas.height;
btnLoadPicture.addEventListener(
"change",
(e) => {
const reader = new FileReader();
const file = e.target.files[0];
img.onload = function () {
let scaled = getScaledDim(
img,
ctx.canvas.dataMaxWidth,
ctx.canvas.dataMaxHeight
);
ctx.canvas.width = scaled.width;
ctx.canvas.height = scaled.height;
ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
};
reader.onloadend = function () {
img.src = reader.result;
};
reader.readAsDataURL(file);
e.target.value = "";
hideButton();
highlightButton(2);
},
false
);
function getScaledDim(img, maxWidth, maxHeight) {
let scaled = {
ratio: img.width / img.height,
width: img.width,
height: img.height,
};
if (scaled.width > maxWidth) {
scaled.width = maxWidth;
scaled.height = scaled.width / scaled.ratio;
}
if (scaled.height > maxHeight) {
scaled.height = maxHeight;
scaled.width = scaled.height / scaled.ratio;
}
return scaled;
}
// canvas
let i = 0;
function setImage() {
img.setAttribute("crossOrigin", "anonymous");
const index = i % images.length;
let currentTime = new Date();
if (currentTime.getHours() == 6 || currentTime.getHours() < 12) {
const imageSrc = imageBaseMorning + images[index];
img.src = imageSrc;
i++;
} else if (currentTime.getHours() == 12 || currentTime.getHours() < 18) {
const imageSrc = imageBaseDay + images[index];
img.src = imageSrc;
i++;
} else if (currentTime.getHours() == 18 || currentTime.getHours() < 24) {
const imageSrc = imageBaseEvening + images[index];
img.src = imageSrc;
i++;
} else if (currentTime.getHours() == 0 || currentTime.getHours() < 6) {
const imageSrc = imageBaseNight + images[index];
img.src = imageSrc;
i++;
}
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
};
}
setImage();
// Save picture function
saveBtn.addEventListener("click", saveButton);
function saveButton() {
const link = document.createElement("a");
link.download = "download.png";
link.href = canvas.toDataURL();
link.style.display = "none";
link.click();
link.remove();
}
});
HTML:
<main class="main">
<div class="filters">
<label>
Blur:
<input
name="blur"
data-sizing="px"
type="range"
min="0"
max="10"
value="0"
id="blur"
/>
<output name="result" for="blur">0</output>
</label>
<label>
Invert:
<input
name="invert"
data-sizing="%"
type="range"
min="0"
max="100"
value="0"
id="invert"
/>
<output name="result">0</output>
</label>
<label>
Sepia:
<input
name="sepia"
data-sizing="%"
type="range"
min="0"
max="100"
value="0"
id="sepia"
/>
<output name="result">0</output>
</label>
<label>
Saturate:
<input
name="saturate"
data-sizing="%"
type="range"
min="0"
max="200"
value="100"
id="saturate"
/>
<output name="result">100</output>
</label>
<label>
Hue rotate:
<input
name="hue-rotate"
data-sizing="deg"
type="range"
min="0"
max="360"
value="0"
id="hue"
/>
<output name="result">0</output>
</label>
</div>
<div class="editor">
<div class="btn-container">
<button class="btn btn-reset">Reset</button>
<button class="btn btn-next btn-active">Next picture</button>
<label class="btn btn-load" for="btnInput">
Load picture
<input
class="btn-load--input"
id="btnInput"
name="upload"
type="file"
placeholder="Load picture"
/>
</label>
<button class="btn btn-save">Save picture</button>
</div>
<canvas width="1600" height="900"></canvas>
</div>
</main>
解决方案
推荐阅读
- php - 如何在表单上获得单选按钮以“调用”后续字段?
- php - 我想使用 PHP 和 gcm 向特定用户发送推送通知
- erlang - 这个 ejabberd / erlang 堆栈跟踪是什么意思?
- typescript - 导入反射元数据时无法编译 TypeScript
- vb.net - 将包含名称的文本文件加载到文本框
- checkbox - Xamarin 窗体为 CheckBox 控件创建 Clicked 事件
- selenium - 无法从登录弹出页面传递到 Selenium 中的密码弹出页面
- unity3d - Unity输入字段未在更改时设置值
- android - 避免将 null 作为视图根传递(在 AlertDialog 中膨胀布局时)
- javascript - Github 高严重性安全漏洞:带有 Node.js 应用程序的 GHSA-7fhm-mqm4-2wp7