zoukankan      html  css  js  c++  java
  • js图片随鼠标移动,旋转,拉伸

    效果如图,图片可以跟随鼠标移动,旋转,拉伸,代码在谷歌浏览器和IE11验证了,其他浏览器没试过
    本博客源码: https://github.com/shengbid/vue-demo 把这个功能放在vue项目里了, 这个项目里会把平时博客写的一些功能的代码都放在里面,有需要可以下载看看,有帮助的话点个star哈
     
    我主要讲一下实现思路,
    首先是移动,这个比较简单
    这里我用的是鼠标事件的pageX,pageY,因为这个获取的是鼠标距文档左上角的坐标,不受滚动条影响


    画一张图来演示
    如图.绿色是鼠标移动位置,pageX,pageY是鼠标按下的位置,pageX1,pageY1是鼠标移动停止时的位置
    pageX是由图片的left + 鼠标到图片左边的距离组成,也许还有其他的padding,margin之类的,但是不影响,统统都算成c
    pageX = left + c
    c = pageX - left
    要求第二次的left值,只需要用pageX1 - c就可以
    left1 = pageX1 - c

    再把计算出的left1赋值给定位元素,top是同样的计算
    因为我的图片是包在一个div元素里,定位给就这个div赋值
     
    代码实现
    // 元素移动
      var moveMouse = false;
      $('.img').mousedown(function (e) {
        e.preventDefault()
        e.stopPropagation()
        moveMouse = true
    
        var dis = {
          X: e.pageX - $('.box').position().left,
          Y: e.pageY - $('.box').position().top
        }
        $(document).on('mousemove', function (event) {
          event.preventDefault()
          event.stopPropagation()
          if (moveMouse) {
            var end = {}
            end.X = event.pageX - dis.X
            end.Y = event.pageY - dis.Y
            $('.box').css({
              'left': end.X,
              'top': end.Y
            })
          }
        })
      })
    
      $(document).on('mouseup', function (e) {
        moveMouse = false
      });
    这样就实现移动功能了

      再来实现元素的旋转拉伸功能
      拉伸可以通过改变元素的width和height实现,也可以通过transform的scale实现
      这里涉及一个问题,旋转的时候以图片左上角为旋转点还是以图片中心点为旋转点,transform的rotate默认是以元素的中心点为旋转点.而width和height的改变是以元素左上角为基点,这里我们要做的功能是边旋转边改变图片大小,那么统一都以图片中心点为基点.这样的话用width和height来实现放大缩小功能就不方便了,所以还是使用scale来实现

      先看旋转的实现,以这张图说明,首先需要确定中心点,还有第一次鼠标按下的点pointB,以后每次旋转都是求BA,CA的夹角,也就是cosA
     代码实现
    var pointA = { // 元素中心点 元素1/2自身宽高 + 元素的定位
        X: $('.box').width() / 2 + $('.box').offset().left,
        Y: $('.box').height() / 2 + $('.box').offset().top
      };
      console.log(pointA)
    
      var pointB = {};
      var pointC = {}; // A,B,C分别代表中心点,起始点,结束点坐标
      // 这里通过鼠标的移动获取起始点和结束点
      var typeMouse = false;
    
      var allA = 0; // 存放鼠标旋转总共的度数
      var count = 0;
      // 元素跟随鼠标移动旋转
      $(".rotate").on('mousedown', function (e) {
        e.preventDefault()
        e.stopPropagation()
    
        typeMouse = true; //获取起始点坐标
        if (count < 1) { // 以鼠标第一次落下的点为起点
          pointB.X = e.pageX;
          pointB.Y = e.pageY;
          count++
        }
    
        console.log(5, pointA, pointB)
    
        $(document).on('mousemove', function (e) {
          e.preventDefault()
          if (typeMouse) {
            pointC.X = e.pageX;
            pointC.Y = e.pageY; // 获取结束点坐标
    
            // 计算出旋转角度
            var AB = {};
            var AC = {};
            AB.X = (pointB.X - pointA.X);
            AB.Y = (pointB.Y - pointA.Y);
            AC.X = (pointC.X - pointA.X);
            AC.Y = (pointC.Y - pointA.Y); // 分别求出AB,AC的向量坐标表示
            var direct = (AB.X * AC.Y) - (AB.Y * AC.X); // AB与AC叉乘求出逆时针还是顺时针旋转
            var lengthAB = Math.sqrt(Math.pow(pointA.X - pointB.X, 2) +
                Math.pow(pointA.Y - pointB.Y, 2)),
              lengthAC = Math.sqrt(Math.pow(pointA.X - pointC.X, 2) +
                Math.pow(pointA.Y - pointC.Y, 2)),
              lengthBC = Math.sqrt(Math.pow(pointB.X - pointC.X, 2) +
                Math.pow(pointB.Y - pointC.Y, 2));
            var cosA = (Math.pow(lengthAB, 2) + Math.pow(lengthAC, 2) - Math.pow(lengthBC, 2)) /
              (2 * lengthAB * lengthAC); //   余弦定理求出旋转角
            var angleA = Math.round(Math.acos(cosA) * 180 / Math.PI);
            if (direct < 0) {
              allA = -angleA; //叉乘结果为负表示逆时针旋转, 逆时针旋转减度数
            } else {
              allA = angleA; //叉乘结果为正表示顺时针旋转,顺时针旋转加度数
            }
    
            // console.log(allA)
            $('.img-box').css('transform', 'rotate('+allA+'deg)')
          }
        });
      });
    
      $(document).on('mouseup', function (e) {
        typeMouse = false;
      });
    拉伸实现,如图,其实就是AC/AB的比例,AB和AC的长度可以百度搜索已知两点坐标求直线距离查看计算公式,这里就不展开了
    代码实现
    // 元素跟随鼠标移动拉伸
      $(".rotate, .rotate1").on('mousedown', function (e) {
        e.preventDefault()
        e.stopPropagation()
    
        typeMouse = true; //获取起始点坐标
        if (count < 1) { // 以鼠标第一次落下的点为起点
          pointB.X = e.pageX;
          pointB.Y = e.pageY;
          count++
        }
        console.log(5, pointA, pointB)
    
        $(document).on('mousemove', function (e) {
          e.preventDefault()
          if (typeMouse) {
            pointC.X = e.pageX;
            pointC.Y = e.pageY; // 获取结束点坐标
            // 计算每次移动元素的半径变化,用作拉伸
            var scalX1 = pointB.X - pointA.X
            var scalY1 = pointB.Y - pointA.Y
            var scalX = pointC.X - pointA.X
            var scalY = pointC.Y - pointA.Y
    
            // 计算出拉伸比例
            var sa = Math.sqrt(scalX1 * scalX1 + scalY1 * scalY1)
            var ss = Math.sqrt(scalX * scalX + scalY * scalY)
            var sc = ss / sa
            // console.log(sc)
            $('.img-box').css('transform', 'scale('+sc+')')
          }
        });
      });
      
      $(document).on('mouseup', function (e) {
        typeMouse = false;
      });

    html代码

      <div class="container">
        <div class="box">
          <div class="img-box">
            <div class="flat">翻转</div>
            <div class="rotate">旋转</div>
            <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1141259048,554497535&fm=26&gp=0.jpg" alt="" class="img">
          </div>
        </div>
      </div>
     
    HTML元素的关系,图片需要包三层父级div. img-box包图片,旋转的时候旋转img-box.因为旋转之后left和top值会改变,
    所以需要在包一层box,移动的时候改变left和top就改变box的值.
    最外层的container主要是一个定位,里面的元素都是绝对定位,需要一个相对定位的父元素
     
      然后,这三个功能都实现了,把他们组合在一起,需要注意一点问题
      移动的时候,图片的中心点也改变了,所以每次移动后需要重新计算图片的中心点,对应的pointB点也需要对应的改变
     
      最后,如果你需要四个角都可以旋转,需要计算出不同旋转角之间的角度差
      如图,如果第一次以旋转区域1为起点,点击旋转区域2时就需要加上旋转区域1与旋转区域2直角的夹角,也就是2倍tanA
      如果第二次旋转选的是旋转区域3,那么就需要加上180°.这是顺时针方向,如果反过来逆时针方向就是减去度数差
     
    完整代码
     
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <style>
      html, body {
        margin: 0;
        font-size: 14px;
      }
      .container {
        /* padding: 20px;
        border: 1px solid sienna; */
        position: relative;
      }
      .box {
        position: absolute;
        left: 200px;
        top: 100px;
         400px;
        height: 400px;
        color: #fff;
        /* background-color: rosybrown; */
      }
      .img-box {
        position: absolute;
        /* left: 30px;
        top: 30px; */
         400px;
        height: 400px;
        background-color: sandybrown;
      }
      .flat {
        position: absolute;
        right: -20px;
        top: -20px;
         40px;
        height: 40px;
        background-color: seagreen;
        z-index: 3;
        line-height: 40px;
        text-align: center;
        cursor: default;
      }
      .rotate, .rotate1 {
        position: absolute;
        right: -20px;
        bottom: -20px;
         40px;
        height: 40px;
        background-color: royalblue;
        z-index: 3;
        cursor: se-resize;
        line-height: 40px;
        text-align: center;
      }
      .rotate1 {
        left: -20px;
        right: auto;
      }
      .img {
         100%;
        height: 100%;
        cursor: move;
      }
      .header {
        height: 50px;
      }
    </style>
    <body>
      <div class="header">
        <h1>图形编辑</h1>
      </div>
      <div class="container">
        <div class="box">
          <div class="img-box">
            <div class="flat">翻转</div>
            <div class="rotate">旋转</div>
            <div class="rotate1">旋转</div>
            <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1141259048,554497535&fm=26&gp=0.jpg" alt="" class="img">
          </div>
        </div>
      </div>
    </body>
    <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
      var flat = -1
      // 镜像翻转
      $(".flat").click(function() {
        $(".img").css("transform", "scaleX("+flat+")")
        flat = -flat
      })
    
      var pointA = { // 元素中心点 元素1/2自身宽高 + 元素的定位
        X: $('.box').width() / 2 + $('.box').offset().left,
        Y: $('.box').height() / 2 + $('.box').offset().top
      };
      console.log(pointA, $('.box').position())
    
      var pointB = {};
      var pointC = {}; // A,B,C分别代表中心点,起始点,结束点坐标
      // 这里通过鼠标的移动获取起始点和结束点
      var typeMouse = false;
      var moveMouse = false;
      var allA = 0; // 存放鼠标旋转总共的度数
      var count = 0;
      var mPointB = {} // 移动的B点距离
      var init = {
        count: 0
      }
      var oldTarget = {
        target: null,
        angle: 0
      }
    
      // 元素跟随鼠标移动旋转拉伸
      $(".rotate, .rotate1").on('mousedown', function (e) {
        e.preventDefault()
        e.stopPropagation()
        // 计算两个旋转方块之间的角度
        var tanA = $('.box').width() / $('.box').height()
        var d = Math.round(Math.atan(tanA) * 180 / Math.PI)
      // 如果当前旋转的区域与上一次旋转的区域不一致,需要加上这两个区域之间的角度差2*tanA,这里我只有两个旋转区域,如果有多个区域,需要分别判断
        if (oldTarget.target && oldTarget.target != e.currentTarget) {
          if (e.currentTarget == $('.rotate')[0]) {
            oldTarget.angle = 2 * d
          } else {
            oldTarget.angle = -2 * d
          }
        } else {
          oldTarget.angle = 0
        }
    
        typeMouse = true; //获取起始点坐标
        if (count < 1) { // 以鼠标第一次落下的点为起点
          pointB.X = e.pageX;
          pointB.Y = e.pageY;
          init.count = 0
          oldTarget.target = e.currentTarget // 储存第一次落下的旋转区域
          count++
        }
        if (mPointB.flag) { // 如果移动后,元素的B点也需要加上平移的距离
          pointB.X += mPointB.X
          pointB.Y += mPointB.Y
          mPointB.flag = false
          init.count = 0
        }
        console.log(5, pointA, pointB)
    
        $(document).on('mousemove', function (e) {
          e.preventDefault()
          if (typeMouse) {
            pointC.X = e.pageX;
            pointC.Y = e.pageY; // 获取结束点坐标
            // 计算每次移动元素的半径变化,用作拉伸
            var scalX1 = pointB.X - pointA.X
            var scalY1 = pointB.Y - pointA.Y
            var scalX = pointC.X - pointA.X
            var scalY = pointC.Y - pointA.Y
    
            // 计算出旋转角度
            var AB = {};
            var AC = {};
            AB.X = (pointB.X - pointA.X);
            AB.Y = (pointB.Y - pointA.Y);
            AC.X = (pointC.X - pointA.X);
            AC.Y = (pointC.Y - pointA.Y); // 分别求出AB,AC的向量坐标表示
            var direct = (AB.X * AC.Y) - (AB.Y * AC.X); // AB与AC叉乘求出逆时针还是顺时针旋转
            var lengthAB = Math.sqrt(Math.pow(pointA.X - pointB.X, 2) +
                Math.pow(pointA.Y - pointB.Y, 2)),
              lengthAC = Math.sqrt(Math.pow(pointA.X - pointC.X, 2) +
                Math.pow(pointA.Y - pointC.Y, 2)),
              lengthBC = Math.sqrt(Math.pow(pointB.X - pointC.X, 2) +
                Math.pow(pointB.Y - pointC.Y, 2));
            var cosA = (Math.pow(lengthAB, 2) + Math.pow(lengthAC, 2) - Math.pow(lengthBC, 2)) /
              (2 * lengthAB * lengthAC); //   余弦定理求出旋转角
            var angleA = Math.round(Math.acos(cosA) * 180 / Math.PI);
            if (direct < 0) {
              allA = -angleA; //叉乘结果为负表示逆时针旋转, 逆时针旋转减度数
            } else {
              allA = angleA; //叉乘结果为正表示顺时针旋转,顺时针旋转加度数
            }
    
            allA += oldTarget.angle
            // $('.img-box').css('transform', 'rotate('+allA+'deg)')
    
            // 计算出拉伸比例
            var sa = Math.sqrt(scalX1 * scalX1 + scalY1 * scalY1)
            var ss = Math.sqrt(scalX * scalX + scalY * scalY)
            var sc = ss / sa
            // console.log(allA, sc)
            $('.img-box').css('transform', 'rotate('+allA+'deg) scale('+sc+')')
          }
        });
      });
    
      // 元素移动
      $('.img').mousedown(function (e) {
        e.preventDefault()
        e.stopPropagation()
        moveMouse = true
        if (init.count < 1) {
          init = {
            X: e.pageX,
            Y: e.pageY,
            count: 1
          }
        }
        var dis = {
          X: e.pageX - $('.box').position().left,
          Y: e.pageY - $('.box').position().top
        }
        $(document).on('mousemove', function (event) {
          event.preventDefault()
          event.stopPropagation()
          if (moveMouse) {
            var end = {}
            end.X = event.pageX - dis.X
            end.Y = event.pageY - dis.Y
            $('.box').css({
              'left': end.X,
              'top': end.Y
            })
            // console.log($('.box').offset(), $('.box').position(), end, dis)
    
            pointA = { // 移动后,重新计算元素中心点 元素1/2自身宽高 + 元素的定位
              X: $('.box').width() / 2 + $('.box').offset().left,
              Y: $('.box').height() / 2 + $('.box').offset().top
            };
            if (count > 0) { // 保存移动的距离
              mPointB.X = event.pageX - init.X
              mPointB.Y = event.pageY - init.Y
              mPointB.flag = true
            }
            // console.log(pointA, mPointB)
          }
        })
      })
      $(document).on('mouseup', function (e) {
        typeMouse = false;
        moveMouse = false
      });
    
    </script>
    
    </html>
  • 相关阅读:
    JDBC statement的常用方法
    JDBC通过资源文件初始化
    django 常用命令
    pip 设置国内源
    Python中注释与声明
    PyQt5程序基本结构分析
    机器学习中常见的专业术语
    给Linux安装中文的man手册
    Vim:Vim入门级配置
    Linux 目录结构与目录操作
  • 原文地址:https://www.cnblogs.com/steamed-twisted-roll/p/13408245.html
Copyright © 2011-2022 走看看