p5.js - 如何使用 p5.js 使用导入的 gif 保存画布?
问题描述
我正在画布上创建一个 gif
function preload() {
gif = createImg("GIFS/" + gifId + ".gif");
gif.position(random(-300, 1600), random(-300, 1000));
gif.size(w, w);
}
我正在尝试保存画布:
function mousePressed() {
saveFrames("out", "png", 1, 25);
}
为什么 saveFrames 在没有 gif 的情况下保存画布?
解决方案
createImg()
<img />
只需创建添加到 DOM的 HTML元素。
如果你希望它被 saveFrames 捕获,你需要将它渲染到 p5.js<canvas />
实现这一点的一种方法是使用drawingContext
调用drawImage()
which 应该将<img />
内容绘制到 p5.js 的画布中。
如果会是这样的:
function preload() {
gif = createImg("GIFS/" + gifId + ".gif");
}
function setup(){
drawingContext.drawImage(gif.elt, random(-300, 1600), random(-300, 1000), w, w);
}
请注意,代码未经测试,但希望能说明这个想法。如果gif
未完全加载,setup()
您可能希望在加载回调中执行此操作。此外,如果 gif 是动画的,您可能需要根据 gif 帧进行多次渲染。
这是一个基本的演示:
// load and display an HTML <img /> element in p5.js' canvas
let imgElement;
function setup() {
createCanvas(400, 400);
imgElement = createImg(
'https://p5js.org/assets/img/asterisk-01.png',
'the p5 magenta asterisk'
);
// hide <img /> element
imgElement.hide();
}
// render <img /> into p5.js canvas
function renderImg(anyImg, x, y, w, h){
drawingContext.drawImage(anyImg.elt, x, y, w, h);
}
function draw(){
let imgSize = random(24, 144);
renderImg(imgElement, random(-144, width), random(-144, height), imgSize, imgSize);
}
function keyPressed(){
if(key == 's' || key == 'S'){
saveFrames("out", "png", 1, 15);
console.log("saving frames -> test on a local webserver");
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.0/p5.min.js"></script>
请注意,这saveFrames()
在上面的演示中不起作用:您需要使用本地网络服务器。
此外,如果您需要记录超过 15 帧,您可以使用ccapture.js库(如 p5.js 参考建议的那样)
更新对于进一步的 gif 操作,您可能需要一个可以解码 gif 文件的 js 库。那里可能有很多。这是一个使用gifler渲染到 p5.js 画布中的基本示例
var frames = 0;
var p5Canvas;
function setup(){
p5Canvas = createCanvas(600, 600);
// Load the GIF, set custom frame render function
gifler('http://themadcreator.github.io/gifler/assets/gif/run.gif').frames(p5Canvas.elt, onDrawFrame);
}
function onDrawFrame(ctx, frame) {
// Match width/height to remove distortion
ctx.canvas.width = ctx.canvas.offsetWidth;
ctx.canvas.height = ctx.canvas.offsetHeight;
// Determine how many pikachus will fit on screen
var n = Math.floor((ctx.canvas.width)/150)
for(var x = 0; x < n; x++) {
// Draw a pikachu
var left = x * 150;
ctx.globalCompositeOperation = 'source-over';
ctx.drawImage(frame.buffer, frame.x + left, frame.y, 150, 100);
// Composite a color
var hue = (frames * 10 + x * 50) % 360;
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = 'hsla(' + hue + ', 100%, 50%, 0.5)';
ctx.fillRect(left, 0, 150, this.height);
}
frames++;
}
<script src="http://themadcreator.github.io/gifler/assets/gifler.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.0/p5.min.js"></script>
var gifFrames;
var offscreenCanvas;
function setup(){
// make an offscreen canvas (of gif dimensions) to render the gif into
offscreenCanvas = createElement('canvas');
// hide offscreen canvas
offscreenCanvas.hide();
// main p5 canvas to use
createCanvas(600, 600);
// Load the GIF, set custom frame render function
gifler('http://themadcreator.github.io/gifler/assets/gif/run.gif').animate(offscreenCanvas.elt).then( function(result){
// extract canvas element of each frame
gifFrames = result._frames;
} );
}
function draw(){
// if the gif frames are ready
if(gifFrames){
// pick a frame
let gifFrame = gifFrames[frameCount % gifFrames.length];
// if the canvas of the frame is ready to be accessed
if(gifFrame.buffer){
// render the frame at random positions and sizes
let randomSize = random(32, 192);
drawingContext.drawImage(gifFrame.buffer, random(-192, width), random(-192, height), randomSize, randomSize);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.0/p5.min.js"></script>
<script src="http://themadcreator.github.io/gifler/assets/gifler.js"></script>
更新原来p5.Image
已经提供了 gif 支持,包括对帧的控制(例如getCurrentFrame()
/ numFrames()
/ setFrame()
/ reset()
/ play()
/ pause()
/ delay()
)
这使它更容易,并且不需要其他 js 库:
let randomLocations = [];
let gif;
function preload(){
gif = loadImage("http://themadcreator.github.io/gifler/assets/gif/run.gif");
}
function setup(){
createCanvas(600, 600);
mousePressed();
}
function mousePressed(){
randomLocations.push(createVector(random(width), random(height)));
}
function draw(){
background(255);
for(let i = 0 ; i < randomLocations.length; i++){
let loc = randomLocations[i];
image(gif, loc.x, loc.y, 64, 64);
}
text("click to add new random position", 10, 15);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.0/p5.min.js"></script>
推荐阅读
- firebase - 自定义无效的动态链接页面
- javascript - 更新 JSON 以使用 react-jsonschema-form 格式
- elasticsearch - 在两个系统中更新记录的系统设计:并行与串行?
- javascript - 在 javascript 中捕获多种类型的错误
- python - Python - 基于 2 个值合并字典列表
- sql - SQL 查找具有下一个最佳时间戳匹配的行对
- javascript - 我有 ?(问号)关于由 sequelize 生成的更新语句
- python - python manage.py collectstatic
- java - 禁用选定端口的 Spring Security [使用 WebFlux Security]
- java - syso 插入快捷方式在 Eclipse 中不起作用