Javascript を WKWebView の中で使う Swift3
WKWebViewをaddSubviewしたviewの中でJavascriptを実行してみたいと思います。概念的な理解を優先するために、クリック処理などのちょっと複雑な処理は書かず、ローカルでhtml,css,JavascriptをXcodeに取り込み、下記のような紙吹雪アニメーションをJavascriptで表現してみたいと思います。Javascriptの優れたUIの力をお借りしたいと思います(紙吹雪はただのコピペテンプレートです)
ファイルの状況
Swift3
まずはWebKitをインポートます
import WebKit
WKNavigationDelegateを継承します
class ViewController: UIViewController, WKNavigationDelegate {
WKWebViewを作ります
let webView: WKWebView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
webView.frame = view.bounds
webView.navigationDelegate = self
webView.scrollView.bounces = false
view.addSubview(webView)
viewDidLoadの中でhtmlを読み込みます
let url = Bundle.main.url(forResource: "index", withExtension: ".html")!
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
}
完成形
import UIKit
//import JavaScriptCore
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
let webView: WKWebView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
webView.frame = view.bounds
webView.navigationDelegate = self
webView.scrollView.bounces = false
view.addSubview(webView)
let url = Bundle.main.url(forResource: "index", withExtension: ".html")!
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Title</title>
<meta charset="utf-8">
<!-- 画面の大きさを制御している-->
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<!-- <link rel="stylesheet" type="text/css" href="main.css" />-->
</head>
<body>
<h1>Call Javascript from Swift3 On Xcode8</h1>
<!-- </br>-->
<!-- </br>-->
<!-- </br>-->
<!-- </br>-->
<!-- <div id="col">Javascripでこの部分を赤色にします</div>-->
<canvas id="canvas"></canvas>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
css
body { background: lightgray; }
Javascript
//即時関数
(function() {
//document.getElementById("col").style.color = "red";
/*
下記コピペ
*/
// forked from dobin's "forked: [canvas] 紙ふぶき" https://jsdo.it/dobin/qEcf
// forked from Shingo.Shibamoto's "forked: [canvas] 紙ふぶき" https://jsdo.it/Shingo.Shibamoto/llOI
// forked from teetteet's "forked: [canvas] 紙ふぶき" https://jsdo.it/teetteet/r8As
// forked from ikr7's "forked: [canvas] 紙ふぶき" https://jsdo.it/ikr7/nutG
// forked from tsubao's "[canvas] 紙ふぶき" https://jsdo.it/tsubao/iR2g
var DEF_KAMIKIRE_MAX = 1000;
var kamikire_array = [];
var cvs;
var ctx;
var stageWidth, stageHeight;
var resizeFlg = true;
//
window.onload = function()
{
init();
}
function hsv2rgb(hue, sat, val) {
var red, grn, blu, i, f, p, q, t;
hue%=360;
if(val==0) {return({r:0, g:0, v:0});}
sat/=100;
val/=100;
hue/=60;
i = Math.floor(hue);
f = hue-i;
p = val*(1-sat);
q = val*(1-(sat*f));
t = val*(1-(sat*(1-f)));
if (i==0) {red=val; grn=t; blu=p;}
else if (i==1) {red=q; grn=val; blu=p;}
else if (i==2) {red=p; grn=val; blu=t;}
else if (i==3) {red=p; grn=q; blu=val;}
else if (i==4) {red=t; grn=p; blu=val;}
else if (i==5) {red=val; grn=p; blu=q;}
red = Math.floor(red*255);
grn = Math.floor(grn*255);
blu = Math.floor(blu*255);
return ({r:red, g:grn, b:blu});
}
//初期処理
function init()
{
cvs = document.getElementById("canvas");
//ウィンドウサイズ設定
stageWidth = window.innerWidth ? window.innerWidth : $(window).width();
stageHeight = window.innerHeight ? window.innerHeight : $(window).height();
cvs.width = stageWidth;
cvs.height = stageHeight;
ctx = cvs.getContext("2d");
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, cvs.width, cvs.height);
//生成
for(var i=0; i<DEF_KAMIKIRE_MAX; i++){
var kami = new Kamikire(10+Math.floor(Math.random()*5));
kami.x = Math.random()*stageWidth;
kami.y = Math.random()*stageHeight;
ctx.fillStyle = "#" + kami._r + kami._g + kami._b;
ctx.fillRect(kami.x, kami.y, kami.SIZE, kami.SIZE);
//
kamikire_array.push(kami);
}
setInterval(EnterFrame, 30);
}
//紙ふぶき
function Kamikire(_size){
this.SIZE = _size;
this.x = 0;
this.y = 0;
this.alpha = 1;
var t = Math.random()*Math.PI*2;
//var r = Math.floor((1+Math.cos(t))*127.9999);
//var g = Math.floor((1+Math.cos(t+Math.PI*2/3))*127.9999);
//var b = Math.floor((1+Math.cos(t-Math.PI*2/3))*127.9999);
var hue = 200;
var sat = 60;
//var val = Math.floor((1+Math.cos(t-Math.PI*2/3))*127.9999);
//var val = 35;
var val = Math.round(Math.random()*50) + 50;
var rgbvalue = hsv2rgb(hue, sat, val);
//ctx.fillStyle = 'rgb('+rgbvalue[r]+','+rgbvalue[g]+','+rgbvalue[b]+')';
//this._r = r;
//this._g = g;
//this._b = b;
this._r = rgbvalue['r'];
this._g = rgbvalue['g'];
this._b = rgbvalue['b'];
this._backColor = 0x010101*Math.floor(127+Math.random()*64);
this._omega = (Math.random()*2-1)*Math.PI/4;
this._fallTheta = 0;
this._fallSpeed = 1+Math.random()*2;
this._theta = Math.random()*Math.PI*2;
this._Ax = 1;
this._Ay = Math.random();
this._Az = Math.random()*2-1;
var _l = Math.sqrt(this._Ax*this._Ax+this._Ay*this._Ay+this._Az*this._Az);
this._Ax /= _l;
this._Ay /= _l;
this._Az /= _l;
var _s = Math.sqrt(this._Ax*this._Ax+this._Ay*this._Ay);
if(_s == 0){ // then A == ( 0, 0, -1 );
this._Bx = 1.0; this._By = 0.0; this._Bz = 0.0;
this._Cx = 0.0; this._Cy = 1.0; this._Cz = 0.0;
} else {
this._Bx = this._Ay; this._By = -this._Ax; this._Bz = 0;
this._Cx = this._Ax*this._Az; this._Cy = this._Ay*this._Az; this._Cz = -(_s*_s);
this._Bx /= _s; this._By /= _s;
this._Cx /= _s*_l; this._Cy /= _s*_l; this._Cz /= _s*_l;
}
}
Kamikire.prototype = {
get rotation3D(){
return this._theta - (Math.PI*2)*Math.floor(this._theta/(Math.PI*2));
},
set rotation3D(theta){
this._theta = theta - (Math.PI*2)*Math.floor(theta/(Math.PI*2));
var _cos = Math.cos(this._theta);
var _sin = Math.sin(this._theta);
// vector F is the rotated image of (1,0,0);
var _Fx = this._Ax*this._Ax+(this._Bx*this._Bx+this._Cx*this._Cx)*_cos;
var _Fy = this._Ax*this._Ay+(this._Bx*this._By+this._Cx*this._Cy)*_cos+(this._Bx*this._Cy-this._Cx*this._By)*_sin;
var _Fz = this._Ax*this._Az+(this._Bx*this._Bz+this._Cx*this._Cz)*_cos-(this._Bx*this._Cz-this._Cx*this._Bz)*_sin;
// vector G is the rotated image of (0,1,0);
var _Gx = this._Ax*this._Ay+(this._By*this._Bx+this._Cy*this._Cz)*_cos+(this._By*this._Cx-this._Cy*this._Bx)*_sin;
var _Gy = this._Ay*this._Ay+(this._By*this._By+this._Cy*this._Cy)*_cos;
var _Gz = this._Ay*this._Az+(this._By*this._Bz+this._Cy*this._Cz)*_cos+(this._By*this._Cz-this._Cy*this._Bz)*_sin;
//
//ctx.fillStyle = 'rgba('+this._r+', '+this._g+', '+this._b+', '+this.alpha+')';
ctx.fillStyle = 'rgb('+this._r+', '+this._g+', '+this._b+')';
//ctx.fillStyle = 'rgb(135, 190, 240)';
//ctx.fillStyle = 'rgb(135, 190, 240)';hsb(.55, 0%, 0%)';
ctx.beginPath();
ctx.lineTo(this.x+-_Fx*this.SIZE/2+_Gx*this.SIZE/2, this.y+-_Fy*this.SIZE/2+_Gy*this.SIZE/2);
ctx.lineTo(this.x+-_Fx*this.SIZE/2-_Gx*this.SIZE/2, this.y+-_Fy*this.SIZE/2-_Gy*this.SIZE/2);
ctx.lineTo(this.x+_Fx*this.SIZE/2-_Gx*this.SIZE/2, this.y+_Fy*this.SIZE/2-_Gy*this.SIZE/2);
ctx.lineTo(this.x+_Fx*this.SIZE/2+_Gx*this.SIZE/2, this.y+_Fy*this.SIZE/2+_Gy*this.SIZE/2);
ctx.closePath();
ctx.fill();
},
fall: function(){
this.rotation3D = this.rotation3D + this._omega;
this.x += this._fallSpeed*Math.sin(this._fallTheta);
this.y += this._fallSpeed*Math.cos(this._fallTheta);
this._fallTheta += (Math.random()*2-1)*Math.PI/12;
if(this._fallTheta < -Math.PI/2){
this._fallTheta = -Math.PI - this._fallTheta;
}
if(this._fallTheta > Math.PI/2){
this._fallTheta = Math.PI - this._fallTheta;
}
}
}
//enterframe
function EnterFrame()
{
//初期化
if(resizeFlg){
resizeFlg = false;
cvs.width = stageWidth;
cvs.height = stageHeight;
}
ctx.clearRect(0,0,stageWidth,stageHeight);
//表示更新
for( i=0; i<DEF_KAMIKIRE_MAX; ++i){
if(kamikire_array[i].y>0){
var par = kamikire_array[i].y / stageHeight;
par = 1 - par;
kamikire_array[i].alpha = par;
}
if(kamikire_array[i].x - kamikire_array[i].SIZE/Math.SQRT2 > stageWidth){
kamikire_array[i].x -= stageWidth;
}
if(kamikire_array[i].x + kamikire_array[i].SIZE/Math.SQRT2 < 0){
kamikire_array[i].x += stageWidth;
}
if(kamikire_array[i].y - kamikire_array[i].SIZE/Math.SQRT2 > stageHeight){
kamikire_array[i].y -= stageHeight;
}
kamikire_array[i].fall();
}
}
/**
* リサイズ
*/
$(window).resize(function(){
resizeFlg = true;
stageWidth = window.innerWidth ? window.innerWidth : $(window).width();
stageHeight = window.innerHeight ? window.innerHeight : $(window).height();
});
})();