RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 876964
Accepted
BlackStar1991
BlackStar1991
Asked:2020-09-04 02:50:10 +0000 UTC2020-09-04 02:50:10 +0000 UTC 2020-09-04 02:50:10 +0000 UTC

如何为背景创建鱼眼效果?SVG

  • 772

您能否告诉我背景图像是否有可能为背景图像创建鱼眼效果?

图片示例:

body {
  position: relative;
  background-color: #d0f0f9;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 80 80'%3E%3Cg fill='%231564e3' fill-opacity='0.4'%3E%3Cpath fill-rule='evenodd' d='M0 0h40v40H0V0zm40 40h40v40H40V40zm0-40h2l-2 2V0zm0 4l4-4h2l-6 6V4zm0 4l8-8h2L40 10V8zm0 4L52 0h2L40 14v-2zm0 4L56 0h2L40 18v-2zm0 4L60 0h2L40 22v-2zm0 4L64 0h2L40 26v-2zm0 4L68 0h2L40 30v-2zm0 4L72 0h2L40 34v-2zm0 4L76 0h2L40 38v-2zm0 4L80 0v2L42 40h-2zm4 0L80 4v2L46 40h-2zm4 0L80 8v2L50 40h-2zm4 0l28-28v2L54 40h-2zm4 0l24-24v2L58 40h-2zm4 0l20-20v2L62 40h-2zm4 0l16-16v2L66 40h-2zm4 0l12-12v2L70 40h-2zm4 0l8-8v2l-6 6h-2zm4 0l4-4v2l-2 2h-2z'/%3E%3C/g%3E%3C/svg%3E");
  margin: 0;
  padding: 0;
  max-height: 100vh;
  overflow: hidden;
}

javascript
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Bharatha
    2020-12-23T13:19:47Z2020-12-23T13:19:47Z

    由于您要为背景创建鱼眼效果,这将是一项耗时的任务,但是您可以创建一个可以加载任何图像的画布(canvas),然后将这个画布放在上面而不是背景上。

    例子

    var bg = document.getElementById('bg'),
        c = document.getElementById('fish-eye'),
        ctx = c.getContext('2d'),
        bgCtx = bg.getContext('2d'),
        src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 80 80'%3E%3Cg fill='%231564e3' fill-opacity='0.4'%3E%3Cpath fill-rule='evenodd' d='M0 0h40v40H0V0zm40 40h40v40H40V40zm0-40h2l-2 2V0zm0 4l4-4h2l-6 6V4zm0 4l8-8h2L40 10V8zm0 4L52 0h2L40 14v-2zm0 4L56 0h2L40 18v-2zm0 4L60 0h2L40 22v-2zm0 4L64 0h2L40 26v-2zm0 4L68 0h2L40 30v-2zm0 4L72 0h2L40 34v-2zm0 4L76 0h2L40 38v-2zm0 4L80 0v2L42 40h-2zm4 0L80 4v2L46 40h-2zm4 0L80 8v2L50 40h-2zm4 0l28-28v2L54 40h-2zm4 0l24-24v2L58 40h-2zm4 0l20-20v2L62 40h-2zm4 0l16-16v2L66 40h-2zm4 0l12-12v2L70 40h-2zm4 0l8-8v2l-6 6h-2zm4 0l4-4v2l-2 2h-2z'/%3E%3C/g%3E%3C/svg%3E";
    
    function loadImg(src)
    {
        var img = new Image();
        img.crossOrigin = 'Anonymous';
        img.onload = function()
        {
            bgCtx.fillStyle = '#d0f0f9';
            bgCtx.fillRect(0, 0, bg.width, bg.height);
    
            for(var x = 0; x < bg.width; x += img.width)
                for(var y = 0; y < bg.height; y += img.height)
                    bgCtx.drawImage(img, x, y, img.width, img.height);
            
            window.removeEventListener('mousemove', distortion);
            window.removeEventListener('touchmove', distortion);
            window.addEventListener('mousemove', distortion);
            window.addEventListener('touchmove', distortion);
        }
        img.src = src;
    }
    loadImg(src);
    
    document.getElementById('file').onchange = function(e)
    {
        var tgt = e.target || e.srcElement;
        loadImg(URL.createObjectURL(tgt.files[0]));
    };
    
    function distortion(e)
    {
        var cx = (e.touches ? e.touches[0].clientX : e.clientX),
            cy = (e.touches ? e.touches[0].clientY : e.clientY),
            size = 200,
            zoom = 1;
        
        c.width = c.height = size;
        c.style.left = cx - size / 2 + 'px';
        c.style.top = cy - size / 2 + 'px';
       
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, size, size);
        ctx.drawImage(
            bg, 
            cx - bg.offsetLeft - .5 * size / zoom, 
            cy - bg.offsetTop - .5 * size / zoom,
            size / zoom, size / zoom, 
            0, 0,
            size, size
        );
        
        var imgData = ctx.getImageData(0, 0, size, size),
            pixels = imgData.data,
            pixelsCopy = [],
            index = 0,
            h = size, w = size,
            i = 0;
        
        for(; i <= pixels.length; i+=4)
        {
            pixelsCopy[index] = [pixels[i], pixels[i+1], pixels[i+2], pixels[i+3]];
            index++;
        }
        
        var result = fisheye(pixelsCopy, w, h);
        
        for(i = 0; i < result.length; i++)
        {
            index = 4 * i;
    
            if(result[i] != undefined)
            {
                pixels[index + 0] = result[i][0];
                pixels[index + 1] = result[i][1];
                pixels[index + 2] = result[i][2]; 
                pixels[index + 3] = result[i][3];
            }
        }
        ctx.putImageData(imgData, 0, 0);
    }
    
    function fisheye(srcpixels, w, h)
    {
        var dstpixels = srcpixels.slice(),
            y = 0;            
       
        for(; y < h; y++)
        {
            var ny = ((2 * y) / h) - 1,
                ny2 = ny * ny,
                x = 0;
    
            for(; x < w; x++)
            {                            
                var nx = ((2 * x) / w) - 1,
                    nx2 = nx * nx,
                    r = Math.sqrt(nx2 + ny2);                
    
                if(0.0 <= r && r <= 1.0)
                {                            
                    var nr = Math.sqrt(1.0-r*r);
                    
                    nr = (r + (1.0-nr)) / 2.0;
    
                    if(nr <= 1.0)
                    {
                        var theta = Math.atan2(ny, nx),
                            nxn = nr * Math.cos(theta),
                            nyn = nr * Math.sin(theta),
                            x2 = parseInt(((nxn + 1) * w) / 2),
                            y2 = parseInt(((nyn + 1) * h) / 2),
                            srcpos = parseInt(y2 * w + x2);
                        
                        if(srcpos >= 0 & srcpos < w * h)
                            dstpixels[parseInt(y * w + x)] = srcpixels[srcpos]
                    }
                }
            }
        }
        return dstpixels
    } 
    body{overflow: hidden; background: #d0f0f9}
    canvas,#button{position: absolute}
    #c{border-radius: 50%; pointer-events: none}
    <canvas id="bg" width="4800" height="4800" style="left:0;top:0"></canvas>
    <canvas id="fish-eye"></canvas>
    
    <input type="file" id="file" style="display:none"><br><br>
    <input type="button" id="button" value="Выбрать файл..." onclick="document.getElementById('file').click()"  style="left:10px;top:10px">

    这是一个链接到一个好的图像上传到这个例子(它必须首先保存为文件)。

    此示例的代码可在此处找到,但最初取自此处。

    另见: https ://ru.wikipedia.org/wiki/Distortion

    • 11
  2. Stranger in the Q
    2020-06-10T00:32:54Z2020-06-10T00:32:54Z

    我将这种效果称为放大镜(放大镜效果)。

    这不是超级难实现,而是片段着色器中的 WebGL / GLSL。

    如果您删除所有基础架构代码,则保留这段代码:

    vec2 c = uv - m; // текстурные координаты минус координаты мыши
    float r = 0.05; // радиус эффекта
    float a = dot(c, c); // дистанция от фрагмента до мышки
    float f = a > r ? a : a + a/2.0*(a/r - 1.0); // сила эффекта
    gl_FragColor = texture2D(tex, m + c*f/a);
    

    let url = "https://picsum.photos/id/28/650/650";
    let gl = canvas.getContext('webgl');
    let loader = new Image();
    loader.crossOrigin = "anonymous";
    loader.src = url;
    loader.onload = function() { 
        
        let z = 1;
        let w = canvas.width = loader.width;
        let h = canvas.height = loader.height;
    
        pid = gl.createProgram();
    
        shader(`
          attribute vec2 coords;
          varying vec2 uv;
          void main(void) {
            uv = coords.xy*0.5 + 0.5;
            gl_Position = vec4(coords.xy, 0.0, 1.0);
          }
        `, gl.VERTEX_SHADER);
    
        shader(`
          precision highp float;
          uniform sampler2D tex;
    
          varying vec2 uv; 
          uniform vec3 m;
    
          void main(void) {
            vec2 c = uv - m.xy;
            float r = 0.05*m.z;
            float a = dot(c, c); 
            float f = a > r ? a : a + a/2.0*(a/r - 1.0);
            gl_FragColor = texture2D(tex, m.xy + c*f/a); 
          }
        `, gl.FRAGMENT_SHADER);
    
        gl.linkProgram(pid);
        gl.useProgram(pid);
    
        gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,3,-1,-1,3,-1]), gl.STATIC_DRAW);
    
        let al = gl.getAttribLocation(pid, "coords");
        gl.vertexAttribPointer(al, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(al);
    
        let texture = gl.createTexture();
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, loader);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.uniform1i(gl.getUniformLocation(pid, "tex"), 0);
     
        let mouseLocation = gl.getUniformLocation(pid, 'm');
    
        gl.viewport(0, 0, w, h);
        gl.clearColor(0, 0, 0, 0);
        
        draw(0, 0);
        
        canvas.addEventListener('mousemove', e => draw(e.layerX, e.layerY));
        canvas.addEventListener('mousewheel', e => draw(e.layerX, e.layerY, 
                  z *= 1 - Math.sign(e.wheelDeltaY)*0.1));
        
        function draw(x, y) {
          gl.uniform3f(mouseLocation, x/w, 1 - y/h, z);
          gl.drawArrays(gl.TRIANGLES, 0, 3);
        }
    }
      
    function shader(src, type) {
      let sid = gl.createShader(type);
      gl.shaderSource(sid, src);
      gl.compileShader(sid);
      gl.attachShader(pid, sid);
    }
    <canvas id="canvas" style="margin:-10px"></canvas>

    PS:现在可以用鼠标滚轮调整半径

    PPS:鱼眼效果,以及去除它的能力,都是在这里实现的,也是通过WebGL/GLSL

    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5