Web控件UI手动摇杆(虚拟手柄)

该文章介绍了一个使用JavaScript和Hammer.js库创建的触摸屏虚拟摇杆控件。这个控件可以根据用户在屏幕上的移动触发跟踪事件,获取轴偏移量等参数,可用于游戏或设备控制。提供了初始化和自定义按钮的功能,并展示了关键代码示例。
摘要由CSDN通过智能技术生成

演示地址:http://tools.pt.wsing.cn/VirtualRocker/

源码下载地址:https://download.csdn.net/download/lyp1215/87583275

触摸屏手动摇杆,根据移动距离触发跟踪事件得到参数:

参数

说明

VirtualRockerID

手柄ID

evType

状态:开始、移动、停止

deltaX

X轴偏移量

deltaY

Y轴偏移量

方法:

名称

描述

参数

Init2Axis

初始一个2轴的控制UI

Init3Axis

初始一个3轴的控制UI

AddVirtualRocker

添加一个摇杆

diameter 手柄直径

x 手柄在页面显示位置 X 坐标

y 手柄在页面显示位置 Y 坐标

crossDirection 十字方向

xAxisNum 手柄移动的X坐标对应板卡轴编号

yAxisNum 手柄移动的Y坐标对应板卡轴编号

AddButton_Circle

添加圆形按钮

title 按钮文字

diameter 按钮直径

x 按钮在页面显示位置 X 坐标

y 按钮在页面显示位置 Y 坐标

AddButton_Radius

添加圆角按钮

title 按钮文字

diameter 按钮直径

x 按钮在页面显示位置 X 坐标

y 按钮在页面显示位置 Y 坐标

click_Callback 点击回调事件

摇杆主要代码:

/*
参数说明:
diameter        手柄直径
x               手柄在页面显示位置 X 坐标
y               手柄在页面显示位置 Y 坐标
crossDirection  十字方向
xAxisNum        手柄移动的X坐标对应板卡轴编号
yAxisNum        手柄移动的Y坐标对应板卡轴编号
*/
function AddVirtualRocker(diameter, x, y, crossDirection, xAxisNum, yAxisNum) {
    //添加摇杆
    crossDirection = crossDirection || false;
    var current_CrossDirection = "";

    var radius = diameter / 2;
    var virtualRockerDiameter = radius;
    var virtualRockerRadius = virtualRockerDiameter / 2;

    var $VirtualRockerBox = $("<div data-kq='control' data-type='VirtualRocker' class='VirtualRockerBox' style='width:" + diameter + "px;height:" + diameter + "px;border-radius:" + diameter + "px;left:" + x + "px; top:" + y + "px;'></div>");
    var $VirtualRocker = $("<div class='VirtualRocker' style='width:" + virtualRockerDiameter + "px;height:" + virtualRockerDiameter + "px;left:" + virtualRockerRadius + "px; top:" + virtualRockerRadius + "px;'></div>");
    $("body").append($VirtualRockerBox);
    $VirtualRockerBox.append($VirtualRocker);

    if (crossDirection) {
        var $VirtualRockerLineX = $("<div class='VirtualRockerLineX' style='left:0px; top:" + radius + "px;'></div>");
        var $VirtualRockerLineY = $("<div class='VirtualRockerLineY' style='left:" + radius + "px; top:0px;'></div>");
    
        $VirtualRockerBox.append($VirtualRockerLineX);
        $VirtualRockerBox.append($VirtualRockerLineY);
    }

    var virtualRockerMove = false;
    var startX, startY, moveEndX, moveEndY;
    var virtualRockerStartX, virtualRockerStartY;

    var hammer1 = "";
    var hammer2 = "";

    var vid = ++_virtualRockerID;
    var panId = 0;
    var hammerVirtualRocker = new Hammer($VirtualRocker[0]);
    hammerVirtualRocker.get('pan').set({ direction: Hammer.DIRECTION_ALL });
    hammerVirtualRocker.on('panstart panmove panend pancancel', function (ev) {
        if (vid == 1) {
            hammer1 += (++panId) + ".VirtualRockerID:" + vid + " evType:" + ev.type + " deltaX:" + ev.deltaX + " deltaY:" + ev.deltaY + "<br>";
            $("#divTips2").html(hammer1);
        }
        else if (vid == 2) {
            hammer2 += (++panId) + ".VirtualRockerID:" + vid + " evType:" + ev.type + " deltaX:" + ev.deltaX + " deltaY:" + ev.deltaY + "<br>";
            $("#divTips2").html(hammer2);
        }
    
        if (ev.type == "panstart") {
            panStart(ev);
        }
        else if (ev.type == "panmove") {
            panMove(ev);
        }
        else if (ev.type == "panend" || ev.type == "pancancel") {
            panEnd(ev);
        }
    });

    function panStart(e) {
    /    /开始移动
        startX = e.deltaX;
        startY = e.deltaY;
    
        virtualRockerStartX = $VirtualRocker.position().left;
        virtualRockerStartY = $VirtualRocker.position().top;
    
        virtualRockerMove = true;
    };
    function panMove(e) {
        if (!virtualRockerMove) return;
    
        moveEndX = e.deltaX;
        moveEndY = e.deltaY;
    
        var moveX = moveEndX - startX, moveY = moveEndY - startY;
        moveX += virtualRockerStartX;
        moveY += virtualRockerStartY;
    
        //超出宽度
        if (moveX <= -virtualRockerRadius) moveX = -virtualRockerRadius;
        if ((moveX + virtualRockerDiameter) > (diameter + virtualRockerRadius)) moveX = (diameter - virtualRockerRadius);
    
        if (moveY <= -virtualRockerRadius) moveY = -virtualRockerRadius;
        if ((moveY + virtualRockerDiameter) > (diameter + virtualRockerRadius)) moveY = (diameter - virtualRockerRadius);
    
        //遥感内圈圆点
        var virtualRockerX = moveX + virtualRockerRadius, virtualRockerY = moveY + virtualRockerRadius;
    
        //移动的距离大于半径时
        var moveRadius = Math.sqrt(Math.pow(Math.abs((virtualRockerX) - radius), 2) + Math.pow(Math.abs((virtualRockerY) - radius), 2));
        if (moveRadius > radius) {
            var isLeft = virtualRockerX - radius < 0;
            var isTop = virtualRockerY - radius < 0;
    
            var p = GetPoint(radius, radius, virtualRockerX, virtualRockerY, radius, radius, radius);
    
            if (isLeft) p = p[1];
            else p = p[0];
    
            moveX = p.x - virtualRockerRadius;
            moveY = p.y - virtualRockerRadius;
        }
    
        var isLeft = (moveX + virtualRockerRadius) - radius < 0;
        var isRight = (moveX + virtualRockerRadius) - radius > 0;
        var isTop = (moveY + virtualRockerRadius) - radius < 0;
        var isBottom = (moveY + virtualRockerRadius) - radius > 0;
    
        if (crossDirection) {
            //十字方向
            if (current_CrossDirection == "") {
            if (parseInt(Math.abs(moveX - radius + virtualRockerRadius)) > parseInt(Math.abs(moveY - radius + virtualRockerRadius))) {
                //X
                moveY = virtualRockerRadius;
                if (current_CrossDirection == "") current_CrossDirection = "X";
            }
            else {
                //Y
                moveX = virtualRockerRadius;
                if (current_CrossDirection == "") current_CrossDirection = "Y";
            }
            }
            else {
            if (current_CrossDirection == "X") {
                moveY = virtualRockerRadius;
            }
            else if (current_CrossDirection == "Y") {
                moveX = virtualRockerRadius;
            }
            }
        }
    
        var posX = parseInt(moveX - radius + virtualRockerRadius);
        var posY = -parseInt(moveY - radius + virtualRockerRadius);
    
        //
        var text = _isOpenGas ? "已连接" : "未连接";
        text += " ";
        text += isLeft ? "左" : isRight ? "右" : "";
        text += isTop ? "上" : isBottom ? "下" : "";
        text += " ";
        text += " X(" + xAxisNum + "):" + posX;
        text += " Y(" + yAxisNum + "):" + posY;
        $("#divTips").text(text);
        //
    
        if (_isOpenGas && (xAxisNum != 0 || yAxisNum != 0)) {
            //摇杆
            JsInterface.VirtualRocker(xAxisNum, yAxisNum, posX, posY, function (flag, msg) {
            if (!flag) {
                $("#divTips").text(msg);
            }
            });
        }
    
        $VirtualRocker.css({ left: moveX + "px", top: moveY + "px" });
        ShowVirtualRockerInfo(moveX, moveY);
    };
    function panEnd(e) {
        //停止移动
        virtualRockerMove = false;
        current_CrossDirection = "";
    
        if (_isOpenGas) {
            //停止运动
            JsInterface.Stop(function (flag, msg) {
            if (!flag) {
                Wsfly.Tips.Info(msg);
            }
            });
        }
    
        $VirtualRocker.css({ left: virtualRockerRadius + "px", top: virtualRockerRadius + "px" });
        HideVirtualRockerInfo();
    };


    function ShowVirtualRockerInfo(moveX, moveY) {
        //显示摇杆信息
        var isLeft = (moveX + virtualRockerRadius) - radius < 0;
        var isRight = (moveX + virtualRockerRadius) - radius > 0;
        var isTop = (moveY + virtualRockerRadius) - radius < 0;
        var isBottom = (moveY + virtualRockerRadius) - radius > 0;
    
        var text = isLeft ? "左" : isRight ? "右" : "";
        text += isTop ? "上" : isBottom ? "下" : "";
    
        text += "X:" + parseInt(Math.abs(moveX - radius + virtualRockerRadius));
        text += " Y:" + parseInt(Math.abs(moveY - radius + virtualRockerRadius));
    
        $("#divVirtualRockerInfo").text(text);
    }
    function HideVirtualRockerInfo() {
        $("#divVirtualRockerInfo").text("");
    }

    /**
     * 求圆和直线之间的交点
     * 直线方程:y = kx + b
     * 圆的方程:(x - m)² + (x - n)² = r²
     * x1, y1 = 线坐标1, x2, y2 = 线坐标2, m, n = 圆坐标, r = 半径
     */
    function GetPoint(x1, y1, x2, y2, m, n, r) {
        let kbArr = binaryEquationGetKB(x1, y1, x2, y2)
        let k = kbArr[0]
        let b = kbArr[1]
    
        let aX = 1 + k * k
        let bX = 2 * k * (b - n) - 2 * m
        let cX = m * m + (b - n) * (b - n) - r * r
    
        let insertPoints = []
        let xArr = quadEquationGetX(aX, bX, cX)
        xArr.forEach(function (x) {
            let y = k * x + b
            insertPoints.push({ x: x, y: y })
        })
        return insertPoints
    }
    /**
     * 求二元一次方程的系数
     * y1 = k * x1 + b => k = (y1 - b) / x1
     * y2 = k * x2 + b => y2 = ((y1 - b) / x1) * x2 + b
     */
    function binaryEquationGetKB(x1, y1, x2, y2) {
        let k = (y1 - y2) / (x1 - x2)
        let b = (x1 * y2 - x2 * y1) / (x1 - x2)
        return [k, b]
    }
    /**
     * 一元二次方程求根
     * ax² + bx + c = 0
     */
    function quadEquationGetX(a, b, c) {
        let xArr = []
        let result = Math.pow(b, 2) - 4 * a * c
        if (result > 0) {
            xArr.push((-b + Math.sqrt(result)) / (2 * a))
            xArr.push((-b - Math.sqrt(result)) / (2 * a))
        } else if (result == 0) {
            xArr.push(-b / (2 * a))
        }
        return xArr
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MOZ-Soft

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值