zlgopen / awtk-web

在浏览器中运行AWTK应用程序
GNU Lesser General Public License v2.1
24 stars 8 forks source link

js触发的按键事件可以传到canvas里吗 #14

Closed Tracker647 closed 3 months ago

Tracker647 commented 5 months ago

有一个需要,给显示界面套上机器外壳,外壳右侧有几个按键,通过这几个按键完成切换焦点和选中的操作,这个机器外壳想实现在html上,这样就不用改已经写好的awtk程序的分辨率,现在不清楚,如果自己给这些按键写js逻辑模拟按键事件触发,按键事件能不能影响到awtk的canvas? 谢谢

xianjimli commented 5 months ago

应该是可以的,你把外壳弄好了,发给我来适配吧。

xianjimli commented 5 months ago

好的

xianjimli commented 5 months ago
截屏2024-06-29 22 34 06
xianjimli commented 5 months ago

做了个例子(还有些小毛病),你可以参考一下:

https://github.com/zlgopen/awtk-web/tree/master/data

用simulator.html覆盖app下的index.html,把simulator_bg.png拷贝到app目录。

Tracker647 commented 5 months ago

不管是鼠标点击模拟按键还是笔记本按键都没法切换焦点。 我用的实现方式是这章的:三、上下左右切换焦点的按键

换成计算器的那个例子,同样到了web笔记本按键换不了焦点。

<window text="Custom Soft Keyboard" anim_hint="htranslate"
  move_focus_up_key="up" move_focus_down_key="down" move_focus_left_key="left" move_focus_right_key="right">

  <edit name="edit" x="c" y="10" w="90%" h="30" focused="true" input_type="custom" text="" tips="custom"/>
  <view y="60" x="c" w="90%" h="-60" is_keyboard="true" grab_keys="true"
    children_layout="default(r=4,c=4,m=5,s=5)" >
    <button focused="true" focusable="true" name="key0" text="0" />
    <button focusable="true" name="key1" text="1" />
    <button focusable="true" name="key2" text="2" />
    <button focusable="true" name="key3" text="3" />
    <button focusable="true" name="key4" text="4" />
    <button focusable="true" name="key5" text="5" />
    <button focusable="true" name="key6" text="6" />
    <button focusable="true" name="key7" text="7" />
    <button focusable="true" name="key8" text="8" />
    <button focusable="true" name="key9" text="9" />
    <button focusable="true" name="key#" text="#" />
    <button focusable="true" name="backspace" text="<=" />
  </view>
</window>

这部分麻烦更新下,谢谢。

xianjimli commented 5 months ago

上下左右键可以在 slider 控件上测试。

Tracker647 commented 5 months ago

上下左右键可以在 slider 控件上测试。

直接用awtk自带的那个demoui吗,不用改其他东西?

Tracker647 commented 5 months ago

上下左右键可以在 slider 控件上测试。

直接用awtk自带的那个demoui吗,不用改其他东西?

不行 到了浏览器点击机器下面按钮,silder是没响应的。

xianjimli commented 5 months ago

先要让slider得到焦点。

Tracker647 commented 5 months ago

补充:解决蓝屏问题: 在.simulator样式加入:

       -moz-user-select: none; /*火狐*//*选中文字时避免出现蓝色背景*/   
      -webkit-user-select: none; /*webkit浏览器*//*选中文字时避免出现蓝色背景*/   
      -ms-user-select: none; /*IE10*//*选中文字时避免出现蓝色背景*/
      user-select: none;/*选中文字时避免出现蓝色背景*/

iframe隐藏滚动条:

<iframe id="app" scrolling="no" class="awtk_app"></iframe>
Tracker647 commented 5 months ago

问下,模拟器html里按钮按下的样式可以怎么弄呢?

Tracker647 commented 5 months ago

问下,模拟器html里按钮按下的样式可以怎么弄呢?

OK, 跟AI对话解决了,自己弄了一个更新,新逻辑事件根据按钮而不是坐标,可以在按钮点击后显示样式。

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<html>

<head>
  <meta charset="UTF-8">
  <title>ZLG AWTK 演示</title>
  <script type="text/javascript" src="js/awtk_web.js"></script>
  <script>
    TBrowser.init();

    function isPointInRect(x, y, rx, ry, rw, rh) {
      return x >= rx && x <= rx + rw && y >= ry && y <= ry + rh;
    }

    function sendKeyEvent(code, name) {
      var iframe = document.getElementById('app');
      var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

      // 创建一个新的键盘事件
      var event = new KeyboardEvent('keydown', {
        key: name,
        keyCode: code,
        code: name,
        which: code,
        bubbles: true
      });

      // 将事件分派到iframe的文档中
      iframeDocument.dispatchEvent(event);

      // 创建一个新的键盘事件
      var event = new KeyboardEvent('keyup', {
        key: name,
        keyCode: code,
        code: name,
        which: code,
        bubbles: true
      });

      iframeDocument.dispatchEvent(event);
    }

    // 确保在文档加载完毕后绑定事件监听器
    document.addEventListener('DOMContentLoaded', function() {
      // 获取各个按钮元素
      var buttonLeft = document.getElementById('buttonLeft');
      var buttonUp = document.getElementById('buttonUp');
      var buttonDown = document.getElementById('buttonDown');
      var buttonRight = document.getElementById('buttonRight');
      var buttonEnter = document.getElementById('buttonEnter');

      // 为左按钮绑定点击事件
      buttonLeft.addEventListener('click', function() {
        sendKeyEvent(37, 'Left');
      });

      // 为上按钮绑定点击事件
      buttonUp.addEventListener('click', function() {
        sendKeyEvent(38, 'Up');
      });

      // 为下按钮绑定点击事件
      buttonDown.addEventListener('click', function() {
        sendKeyEvent(40, 'Down');
      });

      // 为右按钮绑定点击事件
      buttonRight.addEventListener('click', function() {
        sendKeyEvent(39, 'Right');
      });

      // 为回车按钮绑定点击事件
      buttonEnter.addEventListener('click', function() {
        sendKeyEvent(13, 'Enter');
      });
    });

    window.onload = function () {
      const target = 'app.html' + window.location.search;

      if (TBrowser.isMobile()) {
        window.location.href = target
      } else {
        let iframe = document.getElementById('app');
        iframe.width = TBrowser.getParam('width', 800);
        iframe.height = TBrowser.getParam('height', 600);
        iframe.src = target;

        var simulator = document.getElementById('simulator');
        simulator.addEventListener('click', handleSimulatorClicked);
      }
    }
  </script>

  <style>
    .simulator {
      position: relative;
      width: 900px;
      height: 760px;
      background-color: lightgray;
      background-image: url('simulator_bg.png');
      background-position: center;
      background-repeat: no-repeat;
      -moz-user-select: none; /*火狐*//*选中文字时避免出现蓝色背景*/
      -webkit-user-select: none; /*webkit浏览器*//*选中文字时避免出现蓝色背景*/
      -ms-user-select: none; /*IE10*//*选中文字时避免出现蓝色背景*/
      user-select: none;/*选中文字时避免出现蓝色背景*/
    }

    .awtk_app {
      position: relative;
      top: 37px;
      width: 800px;
      height: 600px;
      background-color: skyblue;
    }

    /* 在CSS中设置按钮样式 */
    .button {
      position: absolute;
      border: none;
      background-color: transparent;
      cursor: pointer; /* 将鼠标样式设置为指针,表示可点击 */
    }

    .button-left {
    left: 418px;
    top: 684px;
    width: 32px;
    height: 32px;
    }

    .button-up {
    left: 446px;
    top: 656px;
    width: 32px;
    height: 32px;
    }

    .button-down {
    left: 446px;
    top: 716px;
    width: 32px;
    height: 32px;
    }

    .button-right {
    left: 480px;
    top: 684px;
    width: 32px;
    height: 32px;
    }

    .button-enter {
    left: 450px;
    top: 684px;
    width: 32px;
    height: 32px;
    }

    /* 可以添加一个活动状态样式,用于当按钮被点击时 */
    .button:active {
      /* 添加点击效果,例如改变背景颜色 */
      border: 1px solid #00ffff;
    }

  </style>
</head>

<body>
  <center>
    <div id="simulator" class="simulator">
      <iframe id="app" scrolling="no" class="awtk_app"></iframe>
      <button id="buttonLeft" class="button button-left"></button>
      <button id="buttonUp" class="button button-up"></button>
      <button id="buttonDown" class="button button-down"></button>
      <button id="buttonRight" class="button button-right"></button>
      <button id="buttonEnter" class="button button-enter"></button>
    </div>
  </center>

</html>

谢谢

xianjimli commented 5 months ago

非常好,谢谢。更新了。

Tracker647 commented 5 months ago

还是有点问题的, enter的按键触发后控件会维持在响应keydown的状态,而不是先keydown后keyup,有时得点两次才能达到键盘的效果。 这个麻烦解决下,谢谢。

xianjimli commented 5 months ago

改了,你更新一下awtk-web,用新的simulator.html试试。谢谢

Tracker647 commented 5 months ago

还是有点问题的, enter的按键触发后控件会维持在响应keydown的状态,而不是先keydown后keyup,有时得点两次才能达到键盘的效果。 这个麻烦解决下,谢谢。

解决了,把keydown和keyup做了区分:

function sendKeyEvent(code, name) {
    var iframe = document.getElementById('app');
    var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

    // 创建一个新的键盘事件
    var event = new KeyboardEvent('keydown', {
      key: name,
      keyCode: code,
      code: name,
      which: code,
      bubbles: true
    });

    // 将事件分派到iframe的文档中
    iframeDocument.dispatchEvent(event);

    // 创建一个新的键盘事件
    var event = new KeyboardEvent('keyup', {
      key: name,
      keyCode: code,
      code: name,
      which: code,
      bubbles: true
    });

    iframeDocument.dispatchEvent(event);
  }

function sendKeyDownEvent(code, name) {
      var iframe = document.getElementById('app');
      var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

      // 创建一个新的键盘事件
      var event = new KeyboardEvent('keydown', {
        key: name,
        keyCode: code,
        code: name,
        which: code,
        bubbles: true
      });

      // 将事件分派到iframe的文档中
      iframeDocument.dispatchEvent(event);

    }

    function sendKeyUpEvent(code, name) {
      var iframe = document.getElementById('app');
      var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
       // 创建并派发keyup事件
       var event = new KeyboardEvent('keyup', {
          key: name,
          keyCode: code,
          code: name,
          which: code,
          bubbles: true
        });
        iframeDocument.dispatchEvent(event);
    }

    // 确保在文档加载完毕后绑定事件监听器
    document.addEventListener('DOMContentLoaded', function() {
      // 获取各个按钮元素
      var buttonLeft = document.getElementById('buttonLeft');
      var buttonUp = document.getElementById('buttonUp');
      var buttonDown = document.getElementById('buttonDown');
      var buttonRight = document.getElementById('buttonRight');
      var buttonEnter = document.getElementById('buttonEnter');

      // 为左按钮绑定点击事件
      buttonLeft.addEventListener('click', function() {
        sendKeyEvent(37, 'Left');
      });

      // 为上按钮绑定点击事件
      buttonUp.addEventListener('click', function() {
        sendKeyEvent(38, 'Up');
      });

      // 为下按钮绑定点击事件
      buttonDown.addEventListener('click', function() {
        sendKeyEvent(40, 'Down');
      });

      // 为右按钮绑定点击事件
      buttonRight.addEventListener('click', function() {
        sendKeyEvent(39, 'Right');
      });

      // 为回车按钮绑定点击事件
      buttonEnter.addEventListener('mousedown', function() {
        sendKeyDownEvent(13, 'Enter');
      });

      buttonEnter.addEventListener('mouseup', function() {
        sendKeyUpEvent(13, 'Enter');
      });
    });
Tracker647 commented 5 months ago

改了,你更新一下awtk-web,用新的simulator.html试试。谢谢

好的,谢谢

Tracker647 commented 3 months ago

需求开始复杂了,按钮不只要能切换焦点还要响应界面逻辑。 现在html的js有没有办法去触发awtk内部的逻辑,比如我界面c文件写了个界面逻辑,点击模拟器外部按键能产生一个事件并传参按钮id,在awtk程序内部捕捉到,通过按钮id判断是哪个按钮,进而执行对应的界面逻辑?

xianjimli commented 3 months ago

通过功能键应该可以。

Tracker647 commented 3 months ago

通过功能键应该可以。

必须是硬件按键吗? 可不可以提供一个例子 比如模拟器三个html按钮a,b,c,鼠标点击能够分别触发awtk c程序里对应回调printf,打印a hello world, b hello world这样

Tracker647 commented 3 months ago

通过功能键应该可以。

必须是硬件按键吗? 可不可以提供一个例子 比如模拟器三个html按钮a,b,c,鼠标点击能够分别触发awtk c程序里对应回调printf,打印a hello world, b hello world这样

OK, 想到了,可以用对应按键映射机器按键,用key_down事件去处理。