Mousemove函数在对象拟合时无法正确映射:在CSS中使用

发布于 2025-01-24 17:32:56 字数 4377 浏览 3 评论 0 原文

我正在使用允许用户在鼠标徘徊时从图像中选择颜色的代码。使用对象拟合时:为图像包含颜色无法正确映射。该脚本的作用好像图像被延伸到100%宽度 /高度,而不考虑对象拟合:包含样式。

    <html>
    <head>
    <style>
    *,*:after,*:before{
      -webkit-box-sizing:border-box;
      -moz-box-sizing:border-box;
      box-sizing:border-box;
    }
    
    body{
      width:100%;
      height:100%;
      position:relative;
    }
    
    .thumbnail{
      position:relative;
      display: block;
      overflow:hidden;
      height:100%;
      width:100%;
    }
    
    .thumbnail img {
      display: block;
      cursor: crosshair;
      height: 100%;
      width: 100%;
      object-fit: contain;
    }
    
    #follow {
      position: absolute;
      width: 55px;
      height: 55px;
      border-radius:80%;
      z-index: 99 !important;
      border:2px solid black;
    }
    
    #cs{ 
      display:none;
    }
    
    #color{
      display:none;
    }
    
    }
    </style>
    </head>
    <body>
    <form id=color>
    <input id="hex" type="text"  value="hex">
    </form>
    
    <div class="preview" id="follow"></div>
    <div class="thumbnail">
    
    <img src='[BASE64 IMAGE GOES HERE]'/>       
          </div>
        
          <canvas id="cs"></canvas>
        <script>
        // preview follow mouse
        $(document).mousemove(function(e) {
          $("#follow").css({
            left: e.offsetX,
            top: e.offsetY
          });
        });
        
        // vars
        var img = _('.thumbnail img'),
            canvas = _('#cs'),
            preview = _('.preview'),x = '',y = '';
        
        // click function
        img.addEventListener('click', function(e){
          // chrome
          if(e.offsetX) {
            x = e.offsetX;
            y = e.offsetY; 
          }
          // firefox
          else if(e.layerX) {
            x = e.layerX;
            y = e.layerY;
          }
          useCanvas(canvas,img,function(){
            // get image data
            var p = canvas.getContext('2d')
            .getImageData(x, y, 1, 1).data;
            // show info
         
        color.innerHTML = '<textarea id="hex" type="text"  >'+rgbToHex(p[0],p[1],p[2])+'</textarea>';
        
          });
        },false);
        
        // preview function mousemove
        img.addEventListener('mousemove', function(e){
          // chrome
          if(e.offsetX) {
            x = e.offsetX;
            y = e.offsetY; 
          }
          // firefox
          else if(e.layerX) {
            x = e.layerX;
            y = e.layerY;
          }
          
          useCanvas(canvas,img,function(){
            
            // get image data
            var p = canvas.getContext('2d')
            .getImageData(x, y, 1, 1).data;
            // show preview color
            preview.style.background = rgbToHex(p[0],p[1],p[2]);
          });
        },false);
        
        
        // canvas function
        function useCanvas(el,image,callback){
          el.width = image.width; // img width
          el.height = image.height; // img height
          // draw image in canvas tag
          el.getContext('2d')
          .drawImage(image, 0, 0, image.width, image.height);
          return callback();
        }
        // short querySelector
        function _(el){
          return document.querySelector(el);
        };
        
        // convert rgba to hex 
        // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
        function componentToHex(c) {
          var hex = c.toString(16);
          return hex.length == 1 ? "0" + hex : hex;
        }
        function rgbToHex(r, g, b) {
          return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }
        
        function findPos(obj) {
            var curleft = 0, curtop = 0;
            if (obj.offsetParent) {
                do {
                    curleft += obj.offsetLeft;
                    curtop += obj.offsetTop;
                } while (obj = obj.offsetParent);
                return { x: curleft, y: curtop };
            }
            return undefined;
        }
        </script>
        
        </body>
        </html>

I'm using code that allows a user to select a color from an image when the mouse hovers that pixel. When using object-fit:contain for the image the colors do not map correctly. The script is acting as if the image is stretched to 100% width / 100% height and not taking into account the object-fit:contain style.

    <html>
    <head>
    <style>
    *,*:after,*:before{
      -webkit-box-sizing:border-box;
      -moz-box-sizing:border-box;
      box-sizing:border-box;
    }
    
    body{
      width:100%;
      height:100%;
      position:relative;
    }
    
    .thumbnail{
      position:relative;
      display: block;
      overflow:hidden;
      height:100%;
      width:100%;
    }
    
    .thumbnail img {
      display: block;
      cursor: crosshair;
      height: 100%;
      width: 100%;
      object-fit: contain;
    }
    
    #follow {
      position: absolute;
      width: 55px;
      height: 55px;
      border-radius:80%;
      z-index: 99 !important;
      border:2px solid black;
    }
    
    #cs{ 
      display:none;
    }
    
    #color{
      display:none;
    }
    
    }
    </style>
    </head>
    <body>
    <form id=color>
    <input id="hex" type="text"  value="hex">
    </form>
    
    <div class="preview" id="follow"></div>
    <div class="thumbnail">
    
    <img src='[BASE64 IMAGE GOES HERE]'/>       
          </div>
        
          <canvas id="cs"></canvas>
        <script>
        // preview follow mouse
        $(document).mousemove(function(e) {
          $("#follow").css({
            left: e.offsetX,
            top: e.offsetY
          });
        });
        
        // vars
        var img = _('.thumbnail img'),
            canvas = _('#cs'),
            preview = _('.preview'),x = '',y = '';
        
        // click function
        img.addEventListener('click', function(e){
          // chrome
          if(e.offsetX) {
            x = e.offsetX;
            y = e.offsetY; 
          }
          // firefox
          else if(e.layerX) {
            x = e.layerX;
            y = e.layerY;
          }
          useCanvas(canvas,img,function(){
            // get image data
            var p = canvas.getContext('2d')
            .getImageData(x, y, 1, 1).data;
            // show info
         
        color.innerHTML = '<textarea id="hex" type="text"  >'+rgbToHex(p[0],p[1],p[2])+'</textarea>';
        
          });
        },false);
        
        // preview function mousemove
        img.addEventListener('mousemove', function(e){
          // chrome
          if(e.offsetX) {
            x = e.offsetX;
            y = e.offsetY; 
          }
          // firefox
          else if(e.layerX) {
            x = e.layerX;
            y = e.layerY;
          }
          
          useCanvas(canvas,img,function(){
            
            // get image data
            var p = canvas.getContext('2d')
            .getImageData(x, y, 1, 1).data;
            // show preview color
            preview.style.background = rgbToHex(p[0],p[1],p[2]);
          });
        },false);
        
        
        // canvas function
        function useCanvas(el,image,callback){
          el.width = image.width; // img width
          el.height = image.height; // img height
          // draw image in canvas tag
          el.getContext('2d')
          .drawImage(image, 0, 0, image.width, image.height);
          return callback();
        }
        // short querySelector
        function _(el){
          return document.querySelector(el);
        };
        
        // convert rgba to hex 
        // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
        function componentToHex(c) {
          var hex = c.toString(16);
          return hex.length == 1 ? "0" + hex : hex;
        }
        function rgbToHex(r, g, b) {
          return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }
        
        function findPos(obj) {
            var curleft = 0, curtop = 0;
            if (obj.offsetParent) {
                do {
                    curleft += obj.offsetLeft;
                    curtop += obj.offsetTop;
                } while (obj = obj.offsetParent);
                return { x: curleft, y: curtop };
            }
            return undefined;
        }
        </script>
        
        </body>
        </html>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笛声青案梦长安 2025-01-31 17:32:56

是的,这是因为代码使用了未量的画布图像的副本。

解决此问题的最可靠方法是始终以100%比例显示图像,而不是使用 fit 。如果需要,允许在图像周围铺设,以便用户仍然可以单击其任何部分。 (您可能需要从鼠标事件的XY坐标中减去PAN的偏移尺寸。)

您还可以检测到调整大小规模,然后在 Canvas 中使用时使用它来乘以偏移量,但是这将导致由于四舍五入等原因而导致不准确。

您可能还需要避免浏览器平滑显示的图像,以避免显示源图像中实际上不存在的像素: image Rendering:pixeLated https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering

Yes, that is because the code is using an unscaled canvas copy of the image.

The surest way to fix this is to always display the image at 100% scale instead of using fit. Allow panning around the image if needed so that the user can still click any part of it. (You may need to subtract the offset dimensions of the pan from the xy coordinates of the mouse event.)

You could also detect the resized scale and then use this to multiply the offsets when used in canvas, but this is going to lead to inaccuracies due to rounding and so on.

You may also want to avoid browsers smoothing the displayed image to avoid displaying pixels that don’t actually exist in the source image: image-rendering: pixelated https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文