CocoCreator 2.0.9 定点缩放,手势缩放

本文介绍了一种在Cocos2d-x中实现双手缩放节点的方法,通过监听触摸移动事件和鼠标滚轮事件,动态调整地图节点的缩放比例,同时修正坐标以确保地图显示在合理范围内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 /**
  * 双手缩放节点
  */
cc.Class({
    extends: cc.Component,

    properties: { 
        map:{
            default:null,
            type:cc.Node
        }
    },
 
    onLoad () {
        this.mapScale();
        var minScale = this.getMinScale(); 

        if(Tools.isNull(cc.vv) || Tools.isNull(cc.vv.mapScale)){
            this.map.setScale(1.5,1.5); 
        }else{
            this.map.setScale(cc.vv.mapScale,cc.vv.mapScale); 
        }
        if(cc.vv  && Tools.isValid(cc.vv.mapPos)){
            const pos = cc.vv.mapPos; 
            this.map.setPosition(pos)
            this.fixPos(cc.v2(0,0))
        } 
    }, 

  
    mapScale(){ 
        let parent = this.map; 
        let _this= this;
        let winSize = cc.winSize 
 
        //cc.Canvas.instance.node.on(cc.Node.EventType.TOUCH_MOVE, function (event) {
        this.map.on(cc.Node.EventType.TOUCH_MOVE, function (event) {
            var touches = event.getTouches();
            if (touches.length >= 2) {
                var touch1 = touches[0], touch2 = touches[1];
                var delta1 = touch1.getDelta(), delta2 = touch2.getDelta();
                var touchPoint1 = parent.convertToNodeSpaceAR(touch1.getLocation())
                var touchPoint2 = parent.convertToNodeSpaceAR(touch2.getLocation())
                var distance = touchPoint1.sub(touchPoint2);
                var delta = delta1.sub(delta2);
                var scale = 1;
                if (Math.abs(distance.x) > Math.abs(distance.y)) {
                    scale = (distance.x + delta.x) / distance.x * _this.map.scaleX;
                }
                else {
                    scale = (distance.y + delta.y) / distance.y * _this.map.scaleY;
                }  
                 
                var pos = touchPoint2.add(cc.v2(distance.x/2  ,distance.y/2))  
                //console.log("pos:",Math.floor(pos.x),Math.floor(pos.y));
                //滑轮缩放大小
                var scX = scale;
                //当前缩放值与原来缩放值之差
                var disScale = scX - _this.map.scaleX;
                //当前点击的坐标与缩放值差像乘 
                var gapPos = pos.scale(cc.v2(disScale,disScale));
                //当前node坐标位置减去点击 点击坐标和缩放值的值
                var mapPos = _this.map.getPosition().sub(gapPos);
                //console.log("mapPos:",Math.floor(mapPos.x),Math.floor(mapPos.y));

                //放大缩小
                if(_this.isMinScale(scale)) return;
                if(_this.isMaxScale(scale)) return;
                _this.map.setScale(scale,scale)

                // let pre3 = cc.instantiate(_this.redPre)
                // _this.pre3 = pre3;
                // pre3.setPosition(pos)
                // pre3.scaleX = 2
                // pre3.scaleY = 2
                // _this.map.addChild(pre3);
                //移动地图坐标
                _this.map.setPosition(mapPos)
                _this.fixPos(cc.v2(0,0))
            }else{
                //移动
                 var delta = event.touch.getDelta(); 
                 _this.map.x += delta.x
                 _this.map.y += delta.y
                 _this.fixPos(delta);
            } 
        }, this.map);

       
        //cc.Canvas.instance.node.on('mousewheel', function (event) { 
        this.map.on('mousewheel', function (event) { 
            //点击node的坐标
            var pos = _this.map.convertToNodeSpaceAR(cc.v2(event.getLocationX(),event.getLocationY()));   
            //滑轮缩放大小  
            var scX = (_this.map.scaleX-(event.getScrollY()/10000*-1))
            //当前缩放值与原来缩放值之差
            var disScale = scX - _this.map.scaleX;
            //当前点击的坐标与缩放值差像乘 
            var gapPos = pos.scale(cc.v2(disScale,disScale));
            //当前node坐标位置减去点击 点击坐标和缩放值的值
            var mapPos = _this.map.getPosition().sub(gapPos);
            //console.log("scX",scX)
            if(_this.isMinScale(scX)) return;
            if(_this.isMaxScale(scX)) return;
            //设放大比列  
            _this.map.setScale(scX,scX)
            //移动地图坐标
            _this.map.setPosition(mapPos)
            _this.fixPos(cc.v2(0,0))
        })    
    },

    //是否最大缩放
    isMaxScale(sc){ 
        return sc > 2;
    }, 
    //是否最小缩放
    isMinScale(sc){
        return this.getMinScale() > sc;
    },

    //获取最小缩放比
    getMinScale(){ 
        //console.log(cc.view.getCanvasSize().width,cc.view.getCanvasSize().height)
        //console.log(cc.winSize.width,cc.winSize.height)
        var windowSize = cc.winSize;
        var mapRect = this.map
        var scaleX = windowSize.width/mapRect.width;
        var scaleY = windowSize.height/mapRect.height;
        var scale = scaleX > scaleY ? scaleX : scaleY;
        //console.log("scale",scale)
        return scale;
    },
    
    //修正坐标
    fixPos(delta){  
        var x = this.map.x+delta.x;
        var y = this.map.y+delta.y;    
        let cW  =  this.map.width  * this.map.scaleX
        let cH  = this.map.height * this.map.scaleY

        var winSize = cc.winSize

        var xMin = -cW /2 + winSize.width/2;
        var xMax = cW /2  - winSize.width/2;
        var yMin = -cH/2  + winSize.height/2;
        var yMax  = cH/2  - winSize.height/2;  

        x= x  > xMax  ? xMax  :x
        x = x < xMin  ? xMin  : x;
        y = y > yMax  ? yMax  : y;
        y = y < yMin  ? yMin  :y;   

        //console.log("移动",x,y);
        cc.vv.mapPos = cc.v2(x,y);
        cc.vv.mapScale = this.map.scaleX;
        this.map.setPosition(cc.v2(x,y)) 
    },
    /**
     * 移动到地图指定位置
     * @param {*} x 
     * @param {*} y 
     */
    setMapPos(x,y){
        //移动地图坐标
        if(Tools.isNull(x)){
            x = 0;
        }
        if(Tools.isNull(y)){
            y = 0;
        }  
        let pos = cc.v2(Number(x),Number(y)).scale(cc.v2(this.map.scaleX,this.map.scaleY))  // 849   -3261
        pos = pos.scale(cc.v2(-1,-1));
        this.map.setPosition(pos)
        this.fixPos(cc.v2(0,0))
    },
 

    start () { 

    },
    update (dt) {
         

        
        
     },
});





/**
 * 工具类
 */
var Tools = cc.Class({ 
    statics:{
         /**
             * 
             * @param {最大值} maxNum 
             * @param {最小值} minMum 
             * @returns 返回随机值
             */
            getRandom(maxNum, minMum){
                return Math.floor(Math.random()*(maxNum-minMum+1)+minMum)
            },
        
            isValid(param){
                return !Tools.isNull(param);
            },
        
            getValid(value, defaultValue){
                return Tools.isNull(value) ? defaultValue : value ;
            },
        
            isNull(param){
                return  param == null || param == undefined;
            },
            /**
             * Calculate distant between two points.
             * @param vec1 point1
             * @param vec2 point2
             */
            distance(vec1, vec2) {
                return Math.sqrt(Math.pow(vec1.x - vec2.x, 2) + Math.pow(vec1.y - vec2.y, 2));
            },
        
             /*
            * @startNode     参照节点
            * @targetNdeo    目标节点
            * @customPos 是否自定义坐标
            * */
            convertPos(startNode, targetNdeo, customPos){
                if (!customPos) {
                    customPos = startNode.getPosition()
                }
                let worldPos = startNode.convertToWorldSpaceAR(customPos);
                let pos = targetNdeo.convertToNodeSpaceAR(worldPos);
                return pos;
            },
          
            // 跨天检查
            checkOtherDay(t1, t2, rt) {
                if (this.isNull(t1)) {
                    return false;
                }
                t2 = t2 || 0;
                rt = rt || 0;
        
                if (Math.abs(t2 - t1) > 86400) {
                    return true;
                }
                return t2 > this.figureResetTime(t1, rt);
            },
        
            // 计算重置点
            figureResetTime(t1, rt) {
                var rH = Math.floor(rt / 60 / 60);
                var rM = Math.floor(rt / 60 % 60);
                var rS = Math.floor(rt % 60);
                var dd = new Date(2099, 1, 1, rH, rM, rS);
                var rd = dd.getTime() / 1000;
                return t1 + ((rd - t1) % 86400);
            }, 
        
            //获取当前时间
            getTime(isMs){
                if(Tools.isValid(isMs) && isMs == true)
                {
                    return Math.floor(Date.now());
                }
                let t =  Math.floor(Date.now() /1000);
                return t;
            }, 
        
            random( num ) {
                num = num || 10000;
                return parseInt( Math.random()*num );
            },
           
             
            /**
             * 时间转换字符串格式
             * @param {时间戳} time 
             * @param {格式化} fmt 
             */
            timeToStr(time,fmt) { 
                var o = { 
                    "d+": Math.floor(time / 86400),                    //日
                    "h+": Math.floor((time % 86400) / 3600),                   //小时
                    "m+": Math.floor((time % 3600) / 60),                 //分
                    "s+": Math.floor(time % 60),                 //秒
                } 
                if (/(y+)/.test(fmt))
                    fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
                for (var k in o)
                    if (new RegExp("(" + k + ")").test(fmt))
                        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
                return fmt;
            },
            
            /**
             * h5 获取地址栏参数
             */
            urlParse:function(){
                var params = {};
                if(window.location == null){
                    return params;
                }
                var name,value; 
                var str=window.location.href; //取得整个地址栏
                var num=str.indexOf("?") 
                str=str.substr(num+1); //取得所有参数   stringvar.substr(start [, length ]
                
                var arr=str.split("&"); //各个参数放到数组里
                for(var i=0;i < arr.length;i++){ 
                    num=arr[i].indexOf("="); 
                    if(num>0){ 
                        name=arr[i].substring(0,num);
                        value=arr[i].substr(num+1);
                        params[name]=value;
                    } 
                }
                return params;
            }, 

    },  
})
 
cc.vv = {} //所以创建的一个全局变量 绑定在cc环境而已。
module.exports = Tools;
window.Tools = Tools;

 

先上代码直接拖入场景中绑定到大图上即可。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值