From 1ccc5f45c99a1e576c7dc4a497a7bd4d1944cf3c Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Mon, 15 Jul 2019 17:12:08 +0400 Subject: [PATCH] MNIST WASM --- yarnn-examples/mnist-wasm/.gitignore | 4 ++ yarnn-examples/mnist-wasm/Cargo.toml | 23 +++++++- yarnn-examples/mnist-wasm/index.html | 7 +++ yarnn-examples/mnist-wasm/index.js | 2 + yarnn-examples/mnist-wasm/src/lib.rs | 60 +++++++++++++++++++++ yarnn-examples/mnist-wasm/src/main.rs | 3 -- yarnn-examples/mnist-wasm/webpack.config.js | 27 ++++++++++ 7 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 yarnn-examples/mnist-wasm/.gitignore create mode 100644 yarnn-examples/mnist-wasm/index.html create mode 100644 yarnn-examples/mnist-wasm/index.js create mode 100644 yarnn-examples/mnist-wasm/src/lib.rs delete mode 100644 yarnn-examples/mnist-wasm/src/main.rs create mode 100644 yarnn-examples/mnist-wasm/webpack.config.js diff --git a/yarnn-examples/mnist-wasm/.gitignore b/yarnn-examples/mnist-wasm/.gitignore new file mode 100644 index 0000000..813241d --- /dev/null +++ b/yarnn-examples/mnist-wasm/.gitignore @@ -0,0 +1,4 @@ +/bin +/pkg +*.log + diff --git a/yarnn-examples/mnist-wasm/Cargo.toml b/yarnn-examples/mnist-wasm/Cargo.toml index 047a41f..34a486f 100644 --- a/yarnn-examples/mnist-wasm/Cargo.toml +++ b/yarnn-examples/mnist-wasm/Cargo.toml @@ -4,5 +4,26 @@ version = "0.1.0" authors = ["Andrey Tkachenko "] edition = "2018" +[lib] +crate-type = ["cdylib", "rlib"] + [dependencies] -yarnn = "0.1.0" \ No newline at end of file +yarnn = "0.1" +wasm-bindgen = "0.2" +js-sys = "0.3" + + +[dependencies.web-sys] +version = "0.3" +features = [ + 'CanvasRenderingContext2d', + 'CssStyleDeclaration', + 'Document', + 'Element', + 'EventTarget', + 'HtmlCanvasElement', + 'HtmlElement', + 'MouseEvent', + 'Node', + 'Window', +] diff --git a/yarnn-examples/mnist-wasm/index.html b/yarnn-examples/mnist-wasm/index.html new file mode 100644 index 0000000..512b0fd --- /dev/null +++ b/yarnn-examples/mnist-wasm/index.html @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/yarnn-examples/mnist-wasm/index.js b/yarnn-examples/mnist-wasm/index.js new file mode 100644 index 0000000..fa4f1a2 --- /dev/null +++ b/yarnn-examples/mnist-wasm/index.js @@ -0,0 +1,2 @@ +import('./pkg/yarnn_example_mnist_wasm') + .catch(console.error); \ No newline at end of file diff --git a/yarnn-examples/mnist-wasm/src/lib.rs b/yarnn-examples/mnist-wasm/src/lib.rs new file mode 100644 index 0000000..9b407ef --- /dev/null +++ b/yarnn-examples/mnist-wasm/src/lib.rs @@ -0,0 +1,60 @@ +use std::cell::Cell; +use std::rc::Rc; +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; + +#[wasm_bindgen(start)] +pub fn start() -> Result<(), JsValue> { + let document = web_sys::window().unwrap().document().unwrap(); + let canvas = document + .create_element("canvas")? + .dyn_into::()?; + document.body().unwrap().append_child(&canvas)?; + canvas.set_width(640); + canvas.set_height(480); + canvas.style().set_property("border", "solid")?; + let context = canvas + .get_context("2d")? + .unwrap() + .dyn_into::()?; + let context = Rc::new(context); + let pressed = Rc::new(Cell::new(false)); + { + let context = context.clone(); + let pressed = pressed.clone(); + let closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| { + context.begin_path(); + context.move_to(event.offset_x() as f64, event.offset_y() as f64); + pressed.set(true); + }) as Box); + canvas.add_event_listener_with_callback("mousedown", closure.as_ref().unchecked_ref())?; + closure.forget(); + } + { + let context = context.clone(); + let pressed = pressed.clone(); + let closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| { + if pressed.get() { + context.line_to(event.offset_x() as f64, event.offset_y() as f64); + context.stroke(); + context.begin_path(); + context.move_to(event.offset_x() as f64, event.offset_y() as f64); + } + }) as Box); + canvas.add_event_listener_with_callback("mousemove", closure.as_ref().unchecked_ref())?; + closure.forget(); + } + { + let context = context.clone(); + let pressed = pressed.clone(); + let closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| { + pressed.set(false); + context.line_to(event.offset_x() as f64, event.offset_y() as f64); + context.stroke(); + }) as Box); + canvas.add_event_listener_with_callback("mouseup", closure.as_ref().unchecked_ref())?; + closure.forget(); + } + + Ok(()) +} diff --git a/yarnn-examples/mnist-wasm/src/main.rs b/yarnn-examples/mnist-wasm/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/yarnn-examples/mnist-wasm/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/yarnn-examples/mnist-wasm/webpack.config.js b/yarnn-examples/mnist-wasm/webpack.config.js new file mode 100644 index 0000000..0aa51dc --- /dev/null +++ b/yarnn-examples/mnist-wasm/webpack.config.js @@ -0,0 +1,27 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const webpack = require('webpack'); +const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin"); + +module.exports = { + entry: './index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'index.js', + }, + plugins: [ + new HtmlWebpackPlugin({ + template: 'index.html' + }), + new WasmPackPlugin({ + crateDirectory: path.resolve(__dirname, ".") + }), + // Have this example work in Edge which doesn't ship `TextEncoder` or + // `TextDecoder` at this time. + new webpack.ProvidePlugin({ + TextDecoder: ['text-encoding', 'TextDecoder'], + TextEncoder: ['text-encoding', 'TextEncoder'] + }) + ], + mode: 'development' +}; \ No newline at end of file