js input 框的各种属性设置与应用

一、由3D场景下的坐标点,来绘制一个原生 input 输入框:
/**
     * 绘制输入框
     * @param {THREE.Vector3} point1 
     * @param {THREE.Vector3} point2 
     * @param {string} type 尺寸线类型【position、size】
     * @param {string} axisDir 尺寸线所在轴向
     * @param {string} dir 表示这一条尺寸线,在相机视角下,是左右上下的哪一条
     * @returns {input} 输入框节点
     */
    static makeInput(point1, point2, type, axisDir, dir) {
        if (!type || !axisDir || !dir) return;

        // 主要数据
        const line3 = new THREE.Line3(point1, point2);
        const distance = line3.distance();
        const selected = StorageMgr.datas.SELECTED;

        // 获取输入框需要显示的位置(如果为标识尺寸的,则位置采用【0~1】处,如果标识位置,则采用中心点)
        const centerPoint = type === 'size' ? line3.at(0.3) : line3.getCenter();
        selected.object3d.parent.localToWorld(centerPoint);
        const { top, left } = Compute.d3PosToScreenPos(centerPoint);

        // 创建节点
        const input = globalThis.document && document.createElement('input');

        // 基础样式如下:
        const height = 1.25;
        const width = Tools.setFixed(distance).toString().length / (distance.toString().includes('.') ? 1.8 : 1.5);
        const isH = dir === 'left' || dir === 'right';
        const isV = dir === 'top' || dir === 'bottom';
        input.style.display = 'block';
        input.style.position = 'fixed';
        input.style.top = top + 'px';
        input.style.left = left + 'px';
        input.style.width = `${width}rem`;
        input.style.height = `${height}rem`;
        input.style.textAlign = "center";
        input.style.borderRadius = "3px";

        //* 样式需求如下:
        // 1. 横线显示在下方
        // 2. 竖线显示在右方
        //todo 3. 标尺跟随视角(移动、放大、缩小)
        // 4. 选中输入框时(黑框,白底,黑字)
        // 5. 选中输入框时(默认全选文字,或者光标在最后)
        // 6. 不允许输入非数字和小数点之外的字符
        // 7. 输入错误或输入为空时,保持并重新显示原有数据
        // 8. 输入框禁用滑轮
        input.style.transform = `translateX(${isH ? '-50%' : '0.1rem'}) translateY(${isV ? '-50%' : '0.1rem'})`;
        input.style.border = "unset";
        input.style.background = "#ffffff00";
        input.style.color = "#3d6cdc";
        input.onclick = function (e) {
            this.style.border = "1px solid black"
            this.style.background = "white";
            this.style.color = "black";
            this.focus();
            this.select();
        };
        input.onblur = function (e) {
            this.style.border = "unset";
            this.style.background = "#ffffff00";
            this.style.color = "#3d6cdc";
            this.blur();
        };
        input.type = "number";
        input.className = "dimension-input";
        input.onmousewheel = function (evt) {
            // 禁用滑轮事件
            evt = evt || window.event;
            if (evt.preventDefault) {
                // Firefox  
                evt.preventDefault();
                evt.stopPropagation();
            } else {
                // IE  
                evt.cancelBubble = true;
                evt.returnValue = false;
            }
            return false;
        };
        input.onkeydown = function (e) {
            // 禁用上下按钮的事件
            if (['ArrowUp', 'ArrowDown'].includes(e.key)) return false;
        };

        // 设置用户交互的数据与动作等(回调使用匿名函数,绑定this为回调的调用者)
        input.customPreValue = distance; // 用于计算前后差值的自定义属性
        input.value = Tools.setFixed(distance);
        input.onchange = function (e) {
            this.blur();

            // 输入错误或输入为空时,保持并重新显示原有数据
            if (['', ' '].includes(e.target.value)) return this.value = Tools.setFixed(this.customPreValue);

            // 实例回调
            let value = Number(e.target.value);
            if (type === 'position') value = this.customPreValue - value; // 如果是位置,则传递差值
            selected.onDimensionChange(type, axisDir, value);
            // 以下代码虽会因重绘而无效,但以防万一,做更新
            this.customPreValue = value;
        };

        // 返回输入框
        return input;
    }
二、css 如下:
/* 隐藏number输入框的上下按键 */
.dimension-input::-webkit-outer-spin-button,
.dimension-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
}
.dimension-input[type="number"]{
  -moz-appearance: textfield;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值