Rust利用tauri制作个效率小工具
_十九 人气:0日常使用电脑中经常会用到一个quicke
工具中的轮盘菜单工具。
但quicke免费版很多功能不支持,且它的触发逻辑用的不舒服,经常误触。
本着靠人不让靠自己,自己动手丰衣足食的理念,用tauri撸一个小工具。
先看效果
要解决的问题
唤起方式
因为要通过鼠标进行交互,所以必然会影响系统默认的鼠标行为。
为了减少交互冲突,选择长按右键唤起菜单。
就要解决如下问题:
1、默认情况要阻止右键鼠标的事件传递给操作系统
2、当右键按住时间小于设置长按唤起时间,要自动给系统发送一个右键按下和右键松开的事件
由于tauri没有提供相关的api,所以要从Rust的crate中找看看有没有相关包。
经过一番搜索,找到了rdev
这个包,它提供了基础的系统级的鼠标键盘事件处理。
使用rdev::grab
就可以监听鼠标键盘事件, 并且阻止事件传递
tauri::async_runtime::spawn(async move { rdev::grab(move |event| { let is_block: bool = match event.event_type { EventType::ButtonPress(button) => { match button { Button::Right => { unsafe { !IS_SIMULATE } } _ => { false } } } EventType::ButtonRelease(button) => { match button { Button::Right => { unsafe { !IS_SIMULATE } } _ => { false } } } _ => { false } }; if is_block { None } else { Some(event) } }).unwrap(); });
通过tauri::async_runtime::spawn
创建个异步任务
IS_SIMULATE
是一个全局变量默认false
会阻止右击事件,自动触发事件前会设置为true
,使事件不被阻止,完成后再设置为false
rdev::grab
通过流处理让右键的按下和松开返回个None
阻止事件传递。
菜单出现的位置
我们希望唤起菜单中心在鼠标当前位置,所以
1、获取右击按下时的系统坐标信息
2、把系统的坐标传递给菜单窗口实现定位
由于rdev
的鼠标点击事件没有鼠标位置信息,所以我们要在鼠标移动时保存坐标信息
EventType::MouseMove { x, y } => { unsafe { MOUSE_POSITION = (x, y); } false }
按下鼠标是传递坐标
EventType::ButtonPress(button) => { unsafe { if !IS_SIMULATE { roulette_window.emit("buttondown", ButtonPayload { button: get_button_name(&button), x: MOUSE_POSITION.0, y: MOUSE_POSITION.1 }).unwrap(); } } match button { Button::Right => { unsafe { !IS_SIMULATE } } _ => { false } } }
同时我们把窗口设置全屏展示,这样系统的坐标 == 鼠标在窗口的坐标。
接下来在窗口内绘制需要数量的扇形就完成了基本的制作。
这里使用SVG来绘制扇形菜单
菜单数据:
const config: { id: string; text?: string; image?: string; callback?: () => void; }[] = []
tip: 根据菜单数量已经提前计算path需要的坐标信息
在react内渲染
<svg className='menu' width={SIZE * 2} height={SIZE * 2} xmlns="http://www.w3.org/2000/svg"> <g> <circle id='center' className='center' cx={SIZE} cy={SIZE} r={CENTER_SIZE} /> { active && ( active.id === 'close' ? ( <text className='center-text' x={SIZE} y={SIZE} fill='red' > 关闭 </text> ) : ( <text className='center-text' x={SIZE} y={SIZE} > {active?.text} </text> ) ) } </g> { menu.map(({ id, text, image, points, center }) => ( <g key={id}> <path id={id} className='item' d={`M ${points[0][0]} ${points[0][1]} A ${SIZE} ${SIZE}, 0, 0, 1, ${points[1][0]} ${points[1][1]} L ${points[2][0]} ${points[2][1]} A ${CENTER_SIZE} ${CENTER_SIZE}, 0, 0, 0, ${points[3][0]} ${points[3][1]} Z`} /> { image && ( <image className='item-img' xlinkHref={image} x={center[0] - 15} y={center[1] - 25} width='30' /> ) } { text && ( <text className='item-text' x={center[0]} y={center[1] + 25} > {text} </text> ) } </g> )) } </svg>
在窗口内通过document.addEventListener
监听mousemove
获取鼠标所在的块上,当松开鼠标时就能执行对应的任务。
最后
目前的菜单功能都是写死在代码里的,之后会加上配置功能,并且支持自己编写代码来控制每个菜单对应的具体操作。
后续还可以加上根据焦点应用来分别展示不同的菜单数据。
加载全部内容