Macでもマウスホイールを使う

macmouseJavaScriptからActionScriptを動作させる仕組み、ExternalInterface.addCallbackの使い道の一つとして、「Macでもマウスホイールを使う」ってのがある。Windows版と異なりMac版FlashPlayerでは直接マウスホイールを認識できないので、ブラウザのJavaScriptを経由してaddcallbackを使い、Flash側にマウスホイールがどれくらい動いたかを伝えるのだ。

ライブラリとの組み合わせで解決する方法もあるが、まずは普通に作って理解してみよう。

ExternalInterface.addcallbackを知らない人は、まずは↓を読むこと。
http://www.mztm.jp/2009/06/10/externalinterfaceaddcallback/

↓できあがりはこれ。

ファイル一式 >>ダウンロード

ASのほうは、JSから値を受け取ってスクロールポジションに送っているだけ。
問題はJS側。マウスホイールの値はdelta(デルタ)と呼ばれているのだが、例えばマウスホイールが15度手前に回転した場合に、デルタ値がいくつなのか、マイナスなのかプラスなのかも統一されていないのでJS側でそれを吸収している。ブラウザのバージョンや目的によって、最適値が異なる場合があるので、必ず確認すること。

【参考】
http://adomas.org/javascript-mouse-wheel/
http://f-site.org/articles/2006/09/14175612.html
http://www.ficc.jp/labs/archives/ando/as3_mac/

▼ActionScript3
[sourcecode language=”as3″]
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.external.ExternalInterface;
import fl.containers.ScrollPane;

public class Main extends Sprite{
private var tfStatus:TextField = MakeUI.newTextField([,, 200,, "JSからの命令を待っています。"]);
private var tfValue:TextField = MakeUI.newTextField([,20,200]);
private var shikaku:Sprite = MakeUI.newSprite(null, [["rotation", 45],["mouseEnabled",false]], [["beginFill", [0x00FF00, 0.5]], ["drawRect", [0, 0, 200, 200]]]);
private var sp:ScrollPane = MakeUI.newScrollPane([200, 0, 300, 100, shikaku]);

public function Main():void {
addChild(tfStatus);
addChild(tfValue);
addChild(sp);
ExternalInterface.addCallback("JS2AS", fn);
}
/**
* JSからの命令はExternalInterface.addCallbackを経由して、
* 関数に引き渡されます。
*/
private function fn(myValue:Number):void {
var vsp:Number = Math.max(0, Math.min(sp.verticalScrollPosition – myValue, shikaku.height));
sp.verticalScrollPosition = vsp;
tfStatus.text = "JSからの命令を受け取れました。";
tfValue.text = String(vsp);
}
}
}

import flash.display.DisplayObject;
import fl.containers.ScrollPane;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
class MakeUI {
public static var defaultTextFormat:TextFormat = new TextFormat();
public static function newScrollPane(x_y_w_h_source:Array = null, property:Array = null):ScrollPane {
var i:int;
var sp:ScrollPane = new ScrollPane();
if (x_y_w_h_source) {
if (!x_y_w_h_source[0]) { x_y_w_h_source[0] = 0 };
if (!x_y_w_h_source[1]) { x_y_w_h_source[1] = 0 };
sp.move(x_y_w_h_source[0], x_y_w_h_source[1]);
if (x_y_w_h_source[2] && x_y_w_h_source[3]) { sp.setSize(x_y_w_h_source[2], x_y_w_h_source[3]) };
}
if(property){
for (i = 0; i < property.length; i++) {
if(property[i] && property[i].length > 1){ sp[property[i][0]] = property[i][1] };
}
}
if (x_y_w_h_source.length == 5) {
sp.source = x_y_w_h_source[4];
sp.update();
}
return sp;
}

public static function newSprite(x_y_w_h_sp:Array = null,property:Array=null,graphics:Array=null,addChild:DisplayObject = null):Sprite{
var i:int;
var sp:Sprite;
if(x_y_w_h_sp && x_y_w_h_sp[4]){
sp = x_y_w_h_sp[4];
}else{
sp = new Sprite();
}
if(x_y_w_h_sp){
if (x_y_w_h_sp[0]) { sp.x = x_y_w_h_sp[0] };
if (x_y_w_h_sp[1]) { sp.y = x_y_w_h_sp[1] };
}
if(property){
for (i = 0; i < property.length; i++) {
if(property[i] && property[i].length > 1){sp[property[i][0]] = property[i][1] };
}
}
if(graphics){
for (i = 0; i < graphics.length; i++) {
if(graphics[i] && graphics[i].length > 1){
sp.graphics[graphics[i][0]].apply(graphics[i][2], graphics[i][1]);
}
}
}
if(addChild){ sp.addChild(addChild) };
if(x_y_w_h_sp){
if (x_y_w_h_sp[2]) { sp.width = x_y_w_h_sp[2] };
if (x_y_w_h_sp[3]) { sp.height = x_y_w_h_sp[3] };
}
return sp;
}

public static function newTextField(x_y_w_h_txt_color_alpha:Array = null,property:Array=null,method:Array=null):TextField{
var i:int;
var ta:TextField = new TextField();
ta.defaultTextFormat = defaultTextFormat;
if(x_y_w_h_txt_color_alpha){
if (x_y_w_h_txt_color_alpha[0]) { ta.x = x_y_w_h_txt_color_alpha[0] };
if (x_y_w_h_txt_color_alpha[1]) { ta.y = x_y_w_h_txt_color_alpha[1] };
if (x_y_w_h_txt_color_alpha[2]) { ta.width = x_y_w_h_txt_color_alpha[2] };
if (x_y_w_h_txt_color_alpha[3]) { ta.height = x_y_w_h_txt_color_alpha[3] };
if (x_y_w_h_txt_color_alpha[4]) { ta.text = x_y_w_h_txt_color_alpha[4] };
if (x_y_w_h_txt_color_alpha[5]) { ta.textColor = x_y_w_h_txt_color_alpha[5] };
if (x_y_w_h_txt_color_alpha[6]) { ta.alpha = x_y_w_h_txt_color_alpha[6] };
}
if(property){
for (i = 0; i < property.length; i++) {
if(property[i] && property[i].length > 1){ta[property[i][0]] = property[i][1] };
}
}
if(method){
for (i = 0; i < method.length; i++) {
if(method[i] && method[i].length > 1){
ta[i].apply(method[i][2], method[i][1]);
}
}
}
return ta;
}
}
[/sourcecode]

▼JavaScript
[sourcecode language=”js”]
<script language="javascript">
function wheel(event){
var delta = 0;
if (!event){/* For IE. */
event = window.event;
}
if (event.wheelDelta) {/* IE/Opera. */
delta = event.wheelDelta/120;
/** In Opera 9, delta differs in sign as compared to IE.*/
if (window.opera){
//delta = -delta;
}
if(navigator.userAgent.indexOf("Safari") > -1){
delta = delta/3;
}
} else if (event.detail) {/** Mozilla case. */
delta = -event.detail/3;
}
if (delta){
swfName("test").JS2AS(delta);
}
}
if (window.addEventListener){
/** DOMMouseScroll is for mozilla. */
window.addEventListener(‘DOMMouseScroll’, wheel, false);
}
/** IE/Opera. */
window.onmousewheel = document.onmousewheel = wheel;
function swfName(str) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[str]
}else {
return document[str]
}
}
</script>
[/sourcecode]