前端实现划词翻译

1,612 阅读1分钟

简介

最近接触了一个项目需要实现,类似于bing中的画词翻译功能,于是自己手写实现了一个,拿出来和大家分享,有什么问题欢迎各位大牛指导

要点

1.得到画词的内容,我使用的是jQuery

我设置的是Mouseup 触该事件

 let closeFanyi = false;
  // NOTE  翻译功能
  const fanyiFn = function (e) {
    const text = window.getSelection().toString();
    let $fanyiPanel = $body.find('.fanyi-panel');
  };
  
  // NOTE 监听i.fanyi的mouseover mouseout
  $body.on('mouseup', '.fanyi', (e) => {
    if (closeFanyi) {
      return;
    }
    fanyiFn(e);
  });

2.隐藏面板

一下几点需要注意

  • 1.如果没有面板就创建一个
  • 2.如果有就在上面更改内容
  • 3.点击外面就关闭面板
  • 4.用完记得把点击事件取消掉
// NOTE 隐藏面板
    var hidePanelFun = function (e) {
      e.stopPropagation();
      // NOTE  如果点击面板内部 则不会消失
      if ($fanyiPanel.get(0).contains(e.target)) {
        return;
      }
      $fanyiPanel.hide();
      document.removeEventListener('mousedown', hidePanelFun);
    };


    // NOTE 如果没有就创建
    if (!$fanyiPanel.length) {
      // NOTE 创建fanyipanel
      $fanyiPanel = $('<div class="fanyi-panel"><div class="header"><p class="title"></p><div class="content">翻译无结果</div></div><div class="footer"> <a href="javascript:void(0);" class="close">关闭取词</a></div></div>').appendTo($body);
      // NOTE 取消取词功能
      $fanyiPanel.find('.close').click((e) => {
        e.stopPropagation();
        closeFanyi = true;
        $body.find('.fanyi-panel').hide();
      });
    }

    // NOTE  如果没有选择则关闭面板
    if (!text) {
      $fanyiPanel.hide();
      document.removeEventListener('mousedown', hidePanelFun);
      return;
    }

    

3. 计算位置

  • 因为弹出的面板会有被遮挡的情况,所以需要计算位置

// NOTE  计算Position的位置取到底部
    const position = {
   left: e.pageX,
   top: e.pageY + lineHeight / 2,
    };
    // NOTE 如果文字距离底部的距离小于panel的宽度
    if ((position.top + panelHeight) > bodyHeight) {
      position.top = position.top - lineHeight - panelHeight;
    }

    // NOTE 判断右边的距离是否够panel的宽度
    if ((position.left + panelWidth) > bodyWidth) {
         position.left -= panelWidth;
    }

    // NOTE  先固定好位置
    $fanyiPanel.find('.title').text('');
    $fanyiPanel.find('.content').text('翻译中请稍后。。。。');
    $fanyiPanel.show();
    $fanyiPanel.css({ left: position.left, top: position.top });
    // NOTE 这延迟debounce处理
    fanyiRequestFnDebounce($fanyiPanel, text);
    // NOTE  捕获的时候识别点击
    document.addEventListener('mousedown', hidePanelFun, false);
  };

4.节流的发动请求

为了避免过于频繁的请求 所以必须我自己写了一个节流函数debounce, 这是一个简单的函数,也可以使用Lodash的

function debounce(fn, wait) {
  let timer = null;

  return function () {
    const context = this;
    const args = arguments;
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, wait);
  };
}

// 把结果输入到面板上面
const url ///自己定义服务器的地址 
var fanyiRequestFnDebounce = debounce(($fanyiPanel, text) => {
    httpRequest.start({
      url: '',
      form: {
        q: text,
      },
    }, (ret) => {
      $fanyiPanel.find('.title').text(text);
      $fanyiPanel.find('.content').text(ret.Result.translatedText);
    }, true, url);
  }, 500);

关于翻译的面板样式我就不在这些了 自己随便定义, 技术有限。欢迎大家多多指点