Javascript 调整画布图像大小,如';背景尺寸:封面';反应灵敏 我想做什么 设置背景大小:画布图像上的封面效果 调整窗口大小时重新绘制画布图像(响应) 我试过的

Javascript 调整画布图像大小,如';背景尺寸:封面';反应灵敏 我想做什么 设置背景大小:画布图像上的封面效果 调整窗口大小时重新绘制画布图像(响应) 我试过的,javascript,image,canvas,Javascript,Image,Canvas,我试过下面两种方法。两者都不起作用 问题 图像的纵横比不是固定的 我不确定,但在调整窗口大小时,图像似乎不会被重新渲染 我的代码 函数绘图(){ //得到 const canvas=document.querySelector(“#canvas”); //帆布 const ctx=canvas.getContext('2d'); const cw=画布宽度; const ch=画布高度; //形象 const img=新图像(); img.src=https://source.unsp

我试过下面两种方法。两者都不起作用

  • 问题
    • 图像的纵横比不是固定的
    • 我不确定,但在调整窗口大小时,图像似乎不会被重新渲染
    我的代码
    函数绘图(){
    //得到
    const canvas=document.querySelector(“#canvas”);
    //帆布
    const ctx=canvas.getContext('2d');
    const cw=画布宽度;
    const ch=画布高度;
    //形象
    const img=新图像();
    img.src=https://source.unsplash.com/WLUHO9A_xik/1600x900';
    img.onload=函数(){
    常数iw=img.宽度;
    常数ih=img.高度;
    //“背景尺寸:封面”效果
    常量aspectHeight=ih*(cw/iw);
    常量高度偏移=((aspectHeight-ch)/2)*-1;
    ctx.drawImage(img,0,高度偏移,cw,aspectHeight);
    };
    }
    window.addEventListener(“加载”,绘制);
    window.addEventListener(“调整大小”,绘制)
    
    画布{
    显示:块;
    /*画布宽度取决于父窗口/窗口宽度*/
    宽度:90%;
    高度:300px;
    保证金:0自动;
    边框:1px实心#ddd;
    }
    画布属性不反映与CSS大小相关的实际大小。给定您的代码,
    cw/ch
    固定在
    300/150
    。因此,整个计算都是基于错误的值

    您需要使用实际反映其可见大小的值。喜欢

    一个非常简单的解决方案是在将画布宽度/高度属性用于任何计算之前更新它们。例如:

    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    
    完整示例:

    const canvas=document.querySelector('#canvas');
    const ctx=canvas.getContext('2d');
    //仅加载图像一次
    const img=新承诺(r=>{
    const img=新图像();
    img.src=https://source.unsplash.com/WLUHO9A_xik/1600x900';
    img.onload=()=>r(img);
    });
    const draw=async()=>{
    //调整画布大小以匹配其可见大小
    canvas.width=canvas.clientWidth;
    canvas.height=canvas.clientHeight;
    常量加载=等待img;
    常数iw=加载的宽度;
    常数ih=加载高度;
    const cw=画布宽度;
    const ch=画布高度;
    常数f=数学最大值(cw/iw,ch/ih);
    ctx.setTransform(
    /*比例x*/f,
    /*倾斜x*/0,
    /*歪斜y*/0,
    /*刻度y*/f,
    /*翻译x*/(cw-f*iw)/2,
    /*翻译y*/(ch-f*ih)/2,
    );
    ctx.drawImage(已加载,0,0);
    };
    window.addEventListener(“加载”,绘制);
    window.addEventListener(“调整大小”,绘制)
    
    ——维度{
    宽度:90%;
    高度:300px;
    }
    .——边界{
    边框:3px实心#333;
    }
    帆布{
    显示:块;
    保证金:0自动;
    }
    #试验{
    背景:url(https://source.unsplash.com/WLUHO9A_xik/1600x900)无重复中心;
    背景尺寸:封面;
    保证金:1rem自动0;
    }

    首先,仅加载一次图像,当前每次调整页面大小时都要重新加载图像

    然后,您的变量
    cw
    ch
    将始终是
    300
    150
    ,因为您没有设置画布的大小。记住,它的布局一(由CSS控制)和缓冲区一(由其
    .width
    .height
    属性控制)。
    您可以通过元素的
    .offsetWidth
    .offsetHeight
    属性检索布局值

    最后,您的代码不包含图像大小调整。要做封面,你可以参考你链接的答案,尤其是

    {
    //得到
    const canvas=document.querySelector(“#canvas”);
    //帆布
    const ctx=canvas.getContext('2d');
    //形象
    const img=新图像();
    img.src=https://source.unsplash.com/WLUHO9A_xik/1600x900';
    函数绘图(){
    //获取CSS计算的正确维度
    //并将画布的缓冲区设置为此维度
    const cw=canvas.width=canvas.offsetWidth;
    const ch=canvas.height=canvas.offsetHeight;
    如果(!inp.checked){
    drawImageProp(ctx、img、0、0、cw、ch、0、0);
    }
    }
    img.onload=()=>{
    window.addEventListener(“调整大小”,绘制);
    draw();
    };
    inp.oninput=绘图;
    }
    //肯·菲尔斯滕伯格https://stackoverflow.com/a/21961894/3702797
    函数drawImageProp(ctx、img、x、y、w、h、offsetX、offsetY){
    if(arguments.length==2){
    x=y=0;
    w=ctx.canvas.width;
    h=ctx.canvas.height;
    }
    //默认偏移量为“中心”
    offsetX=offsetX的类型==“编号”?offsetX:0.5;
    offsetY=typeof offsetY==“number”?offsetY:0.5;
    //保持界限[0.0,1.0]
    如果(offsetX<0)offsetX=0;
    如果(偏移量<0)偏移量=0;
    如果(offsetX>1)offsetX=1;
    如果(offsetY>1)offsetY=1;
    var iw=img.width,
    ih=img.高度,
    r=数学最小值(w/iw,h/ih),
    nw=iw*r,//新道具宽度
    nh=ih*r,//新道具高度
    cx,cy,cw,ch,ar=1;
    //决定填补哪个空白
    如果(nwiw)cw=iw;
    如果(ch>ih)ch=ih;
    //在目标矩形中填充图像
    ctx.drawImage(img、cx、cy、cw、ch、x、y、w、h);
    }
    画布{
    显示:块;
    /*画布宽度取决于父窗口/窗口宽度*/
    宽度:90%;
    高度:300px;
    保证金:0自动;
    边框:1px实心#ddd;
    背景图像:url('https://source.unsplash.com/WLUHO9A_xik/1600x900');
    B