2026/03/26

使用游戏手柄控制 Mac 苹果电脑

将你的游戏手柄变成 macOS 生产力工具。通过自定义按键映射、鼠标模拟和即时文本输入,精准控制任何应用。

核心功能

1. 智能应用切换

模拟 Command + Tab 快捷键,在所有 macOS 应用间快速切换和激活。

2. 高级鼠标模拟

  • 左右键点击模拟,支持增强拖拽功能
  • 长按功能 - 按住左键快进 YouTube 视频,流畅浏览
  • 双击支持,快速切换全屏和执行操作
  • 摇杆控制鼠标移动,可调节灵敏度
  • 流畅拖拽窗口和对象
  • 使用手柄完成大部分鼠标/触控板操作

3. 灵活的摇杆模式

每个摇杆可独立配置为三种模式之一:

  • 鼠标模式:精准光标控制,可调节灵敏度
  • 滚动模式:流畅滚动文档、网页和媒体时间轴
  • 按键模式:四个方向映射为任意按键,适合 WASD 移动、方向键导航或自定义快捷键

4. 完整的键盘和手柄映射

将任何键盘输入映射到手柄按键 — 单个按键、组合键(Command + Shift + J)、功能键和媒体控制。轻触触发即时操作,或长按实现连续输入,如快速调节音量或翻页。键盘能做的,手柄也能做。

5. 即时文本输入

文本字符串映射 - 为任意手柄按键分配自定义文本。一键输入用户名、密码、邮箱地址或常用短语。完美简化重复输入任务。

6. 多配置文件支持

  • 单个手柄按键可根据激活的配置文件触发完全不同的按键或快捷键。同一按键可用于快进/快退视频、执行鼠标左键点击或粘贴文档文本
  • 创建无限自定义配置文件,适应不同场景
  • 跨品牌配置文件设置,在不同手柄间保持肌肉记忆
  • 配置文件循环 - 使用专用按键映射即时切换配置文件
  • 可视化配置文件通知 - 切换配置文件时获得可自定义的 HUD 反馈(可调节位置或完全禁用)
  • 同时支持多个手柄

7. 通用应用兼容性

在所有应用中享受无缝控制:

  • 图书:使用方向键翻页,舒适阅读
  • Keynote:使用摇杆启动演示并导航幻灯片
  • 视频播放器(IINA、QuickTime):使用方向键快进视频,完美支持 AirPlay 投屏
  • Safari 和预览:配合 Homerow,快速浏览和查看 PDF
  • 媒体应用:完整媒体键支持(播放/暂停、下一首、上一首、音量)

8. 专业功能

  • Mission Control 集成,用于窗口管理
  • 中文语言支持,自动检测系统语言
  • 多配置文件,即时切换
  • 每个手柄可调节鼠标灵敏度

适用场景

  • 内容创作者和视频编辑
  • 演示专业人士
  • 媒体消费和娱乐
  • 无障碍和人体工学计算

释放手柄的全部潜力,探索与 macOS 交互的新方式。无论是浏览、演示还是创作内容,Game Controller Mapper 都能将你的游戏手柄转变为强大的生产力工具。

注:需要 macOS 辅助功能权限以实现键盘和鼠标模拟。

2009/04/13

一个简单的鼠标手势模拟

Demo

/**
* @author chenqian
* @contact yesterday[at]gmail.com
* @URI www.stopdesign.cn
*/


package
{
import flash.display.*;
import flash.events.*;
import flash.geom.Point;
import flash.text.TextField;

public class MouseGesture extends Sprite
{

public static const GESTURE_UP:String="GESTURE_UP";
public static const GESTURE_RIGHT:String="GESTURE_RIGHT";
public static const GESTURE_DOWN:String="GESTURE_DOWN";
public static const GESTURE_LEFT:String="GESTURE_LEFT";
// the color of the drawing line
public var lineColor:Number;
// the size of the drawing line
public var lineSize:Number;
// where the mouse start drawing
private var _startPoint : Point;
// where the mouse stop drawing
private var _newPoint : Point;
// the drawing direction
private var _direction : String;
// the drawing line
private var _drawLine : Sprite;

public function MouseGesture(...rest){
trace("mouse gesture init")
// default mouse gestrue line color and size
lineColor=0xFF0000;
lineSize= 2;

// parse parameters
if(rest[0] != null){
lineColor = rest[0];

}
if(rest[1] != null){
lineSize=rest[1];
}

//add the shape, used for drawing the gesture
var child:Shape = new Shape();
child.graphics.beginFill(0x000000);
child.graphics.lineStyle(0, 0xFFFFFF);
child.graphics.drawRect(0, 0, 1600, 1600);
child.graphics.endFill();
addChild(child);
child.alpha=0;
_drawLine = new Sprite();
addChild( _drawLine );
addEventListener( MouseEvent.MOUSE_DOWN , mouseDownHandler );
}

// set the gesture color
public function setLineColor(c:Number):void{
lineColor=c;
}

// set the gesture size
public function setLineSize(s:Number):void{
lineSize=s;
}


// fire when user press mouse down
private function mouseDownHandler( e:MouseEvent ):void
{

var _color : Number = lineColor;
var _size : Number = lineSize;
_startPoint = new Point( mouseX , mouseY );
_drawLine.graphics.lineStyle( _size , _color , 1.0 );
_drawLine.graphics.moveTo( _startPoint.x , _startPoint.y );
addEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
addEventListener( MouseEvent.MOUSE_UP , mouseUpHander );
}


// fire when user move the mouse
private function mouseMoveHandler( e:MouseEvent ):void
{
_newPoint = new Point( mouseX , mouseY );
var _distance : Number = Point.distance( _startPoint , _newPoint );
_drawLine.graphics.lineTo( _newPoint.x , _newPoint.y );
}


// fire when user's mouse is up
private function mouseUpHander( e:MouseEvent ):void
{
detectDir();
_drawLine.graphics.clear();
removeEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
removeEventListener( MouseEvent.MOUSE_UP , mouseUpHander );
}


/* detecting the mouse move direction */
private function detectDir():void
{
var _vector:Point = _newPoint.subtract( _startPoint );
var _angle : Number = Math.atan2( _vector.y , _vector.x ) * 180 / Math.PI;
// move down
if ( _angle >= 45 && _angle < 125 ){
dispatchEvent(new Event(MouseGesture.GESTURE_DOWN,true));
removeEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
removeEventListener( MouseEvent.MOUSE_UP , mouseUpHander );
}
// move left
else if ( _angle >= 125 || _angle < -125 ){
dispatchEvent(new Event(MouseGesture.GESTURE_LEFT,true))
removeEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
removeEventListener( MouseEvent.MOUSE_UP , mouseUpHander );

}
// move right
else if ( _angle >= -45 && _angle < 45 ){
dispatchEvent(new Event(MouseGesture.GESTURE_RIGHT,true))
removeEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
removeEventListener( MouseEvent.MOUSE_UP , mouseUpHander );

}
// move up
else if ( _angle >= -125 && _angle < -45 ){
dispatchEvent(new Event(MouseGesture.GESTURE_UP,true))
removeEventListener( MouseEvent.MOUSE_MOVE , mouseMoveHandler );
removeEventListener( MouseEvent.MOUSE_UP , mouseUpHander );

}
}

}

}

标签: , ,

2009/04/09

简单地玩augmented reality

print

把上面这张图片发送到你手机中,比如用gmail发给自己,然后在手机中下载打开,接着前往这个网址,打开摄影头,就有类似的东西出现在你面前了:

更多...

标签: ,

2008/12/27

SIMBL与AIR应用的冲突

如果你在使用 HTML+JS 的方式构建 AIR 应用,那么在 mac 中可能由 SIMBL (Smart InputManager Bundle Loader) 引起 crash,不管应用多简单。解决方法是暂时重命名SIMBL文件夹(或等AIR更新),比如改为: /Library/Application Support/SIMBL01/

标签: ,

2008/12/09

常用的DOM操作、事件

来自:Dustin Diaz,我加上了删除事件。
var Dom = {
get: function(el) {
if (typeof el === 'string') {
return document.getElementById(el);
} else {
return el;
}
},
add: function(el, dest) {
var el = this.get(el);
var dest = this.get(dest);
dest.appendChild(el);
},
remove: function(el) {
var el = this.get(el);
el.parentNode.removeChild(el);
}
};
var Event = {
add: function() {
if (window.addEventListener) {
return function(el, type, fn) {
Dom.get(el).addEventListener(type, fn, false);
};
} else if (window.attachEvent) {
return function(el, type, fn) {
var f = function() {
fn.call(Dom.get(el), window.event);
};
Dom.get(el).attachEvent('on' + type, f);
};
}
}(),
remove:function(){
if (window.removeEventListener) {
return function(el, type,fn) {
Dom.get(el).removeEventListener(type, fn,false);
};
} else if (window.detachEvent) {
return function(el, type, fn) {
Dom.get(el).detachEvent('on' + type);
};
}
}()
};

使用时类似:Event.add('domId', 'click',install);
和 AS 中的 tweener 语法挺像的:
Tweener.addTween(event.displayObject3D, {
rotationY:180,
time:0.5,
transition:"easeOutQuart"
} );

标签: , ,

、