From 62b04e44c423228e6206b65d35c1b293b976d580 Mon Sep 17 00:00:00 2001 From: Anton Danilkin Date: Thu, 13 Sep 2018 02:10:23 +0300 Subject: [PATCH 1/2] Add paint example --- Cargo.toml | 1 + examples/paint/.gitignore | 4 ++ examples/paint/Cargo.toml | 26 +++++++++++ examples/paint/README.md | 15 ++++++ examples/paint/build.sh | 15 ++++++ examples/paint/index.html | 7 +++ examples/paint/index.js | 5 ++ examples/paint/package.json | 11 +++++ examples/paint/src/lib.rs | 78 ++++++++++++++++++++++++++++++++ examples/paint/webpack.config.js | 16 +++++++ 10 files changed, 178 insertions(+) create mode 100644 examples/paint/.gitignore create mode 100644 examples/paint/Cargo.toml create mode 100644 examples/paint/README.md create mode 100755 examples/paint/build.sh create mode 100644 examples/paint/index.html create mode 100644 examples/paint/index.js create mode 100644 examples/paint/package.json create mode 100755 examples/paint/src/lib.rs create mode 100644 examples/paint/webpack.config.js diff --git a/Cargo.toml b/Cargo.toml index 6f93abd48..3c7855766 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,6 +73,7 @@ members = [ "examples/julia_set", "examples/math", "examples/no_modules", + "examples/paint", "examples/performance", "examples/smorgasboard", "examples/wasm-in-wasm", diff --git a/examples/paint/.gitignore b/examples/paint/.gitignore new file mode 100644 index 000000000..4f5a7e185 --- /dev/null +++ b/examples/paint/.gitignore @@ -0,0 +1,4 @@ +package-lock.json +wasm_bindgen_paint.js +wasm_bindgen_paint_bg.js +wasm_bindgen_paint_bg.wasm diff --git a/examples/paint/Cargo.toml b/examples/paint/Cargo.toml new file mode 100644 index 000000000..7ca8c5e59 --- /dev/null +++ b/examples/paint/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "wasm-bindgen-paint" +version = "0.1.0" +authors = ["The wasm-bindgen Developers"] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +js-sys = { path = "../../crates/js-sys" } +wasm-bindgen = { path = "../..", features = ["nightly"] } + +[dependencies.web-sys] +path = "../../crates/web-sys" +features = [ + 'CanvasRenderingContext2d', + 'CssStyleDeclaration', + 'Document', + 'Element', + 'EventTarget', + 'HtmlCanvasElement', + 'HtmlElement', + 'MouseEvent', + 'Node', + 'Window', +] diff --git a/examples/paint/README.md b/examples/paint/README.md new file mode 100644 index 000000000..cc833b697 --- /dev/null +++ b/examples/paint/README.md @@ -0,0 +1,15 @@ +# Paint Example + +This directory is an example of using the `web-sys` crate for making a simple +painting program with all of the logic written in Rust. + +You can build and run the example with: + +``` +$ ./build.sh +``` + +(or running the commands on Windows manually) + +and then opening up `http://localhost:8080/` in a web browser should show a +blank canvas on which you can draw. diff --git a/examples/paint/build.sh b/examples/paint/build.sh new file mode 100755 index 000000000..d5f85599b --- /dev/null +++ b/examples/paint/build.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# For more coments about what's going on here, see the `hello_world` example + +set -ex +cd "$(dirname $0)" + +cargo +nightly build --target wasm32-unknown-unknown + +cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ + --bin wasm-bindgen -- \ + ../../target/wasm32-unknown-unknown/debug/wasm_bindgen_paint.wasm --out-dir . + +npm install +npm run serve diff --git a/examples/paint/index.html b/examples/paint/index.html new file mode 100644 index 000000000..6b7bece10 --- /dev/null +++ b/examples/paint/index.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/examples/paint/index.js b/examples/paint/index.js new file mode 100644 index 000000000..271879195 --- /dev/null +++ b/examples/paint/index.js @@ -0,0 +1,5 @@ +// For more comments about what's going on here, check out the `hello_world` +// example. +import('./wasm_bindgen_paint').then(paint => { + paint.main(); +}); diff --git a/examples/paint/package.json b/examples/paint/package.json new file mode 100644 index 000000000..176a69a49 --- /dev/null +++ b/examples/paint/package.json @@ -0,0 +1,11 @@ +{ + "scripts": { + "serve": "webpack-dev-server" + }, + "devDependencies": { + "html-webpack-plugin": "^3.2.0", + "webpack": "^4.11.1", + "webpack-cli": "^2.0.10", + "webpack-dev-server": "^3.1.0" + } +} diff --git a/examples/paint/src/lib.rs b/examples/paint/src/lib.rs new file mode 100755 index 000000000..6596820f6 --- /dev/null +++ b/examples/paint/src/lib.rs @@ -0,0 +1,78 @@ +extern crate js_sys; +extern crate wasm_bindgen; +extern crate web_sys; + +use std::cell::RefCell; +use std::rc::Rc; +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; + +#[wasm_bindgen] +pub fn main() { + let document = web_sys::Window::document().unwrap(); + let canvas = document + .create_element("canvas") + .unwrap() + .dyn_into::() + .map_err(|_| ()) + .unwrap(); + (document.body().unwrap().as_ref() as &web_sys::Node) + .append_child(canvas.as_ref() as &web_sys::Node) + .unwrap(); + canvas.set_width(640); + canvas.set_height(480); + (canvas.as_ref() as &web_sys::HtmlElement) + .style() + .set_property("border", "solid") + .unwrap(); + let context = canvas + .get_context("2d") + .unwrap() + .unwrap() + .dyn_into::() + .unwrap(); + let context = Rc::new(context); + let pressed = Rc::new(RefCell::new(false)); + { + let context = context.clone(); + let pressed = pressed.clone(); + let closure: Closure = Closure::new(move |event: web_sys::MouseEvent| { + context.begin_path(); + context.move_to(event.offset_x() as f64, event.offset_y() as f64); + *pressed.borrow_mut() = true; + }); + (canvas.as_ref() as &web_sys::EventTarget) + .add_event_listener_with_callback("mousedown", closure.as_ref().unchecked_ref()) + .unwrap(); + closure.forget(); + } + { + let context = context.clone(); + let pressed = pressed.clone(); + let closure: Closure = Closure::new(move |event: web_sys::MouseEvent| { + if *pressed.borrow() { + 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); + } + }); + (canvas.as_ref() as &web_sys::EventTarget) + .add_event_listener_with_callback("mousemove", closure.as_ref().unchecked_ref()) + .unwrap(); + closure.forget(); + } + { + let context = context.clone(); + let pressed = pressed.clone(); + let closure: Closure = Closure::new(move |event: web_sys::MouseEvent| { + *pressed.borrow_mut() = false; + context.line_to(event.offset_x() as f64, event.offset_y() as f64); + context.stroke(); + }); + (canvas.as_ref() as &web_sys::EventTarget) + .add_event_listener_with_callback("mouseup", closure.as_ref().unchecked_ref()) + .unwrap(); + closure.forget(); + } +} diff --git a/examples/paint/webpack.config.js b/examples/paint/webpack.config.js new file mode 100644 index 000000000..453a1a59e --- /dev/null +++ b/examples/paint/webpack.config.js @@ -0,0 +1,16 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); + +module.exports = { + entry: './index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'index.js', + }, + plugins: [ + new HtmlWebpackPlugin({ + template: "index.html" + }) + ], + mode: 'development' +}; From b9cc8e12702b9533ab8e024e3353c4832508edc4 Mon Sep 17 00:00:00 2001 From: Anton Danilkin Date: Thu, 13 Sep 2018 03:38:22 +0300 Subject: [PATCH 2/2] Use Cell instead of RefCell --- examples/paint/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/paint/src/lib.rs b/examples/paint/src/lib.rs index 6596820f6..905b956fe 100755 --- a/examples/paint/src/lib.rs +++ b/examples/paint/src/lib.rs @@ -2,7 +2,7 @@ extern crate js_sys; extern crate wasm_bindgen; extern crate web_sys; -use std::cell::RefCell; +use std::cell::Cell; use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; @@ -32,14 +32,14 @@ pub fn main() { .dyn_into::() .unwrap(); let context = Rc::new(context); - let pressed = Rc::new(RefCell::new(false)); + let pressed = Rc::new(Cell::new(false)); { let context = context.clone(); let pressed = pressed.clone(); let closure: Closure = Closure::new(move |event: web_sys::MouseEvent| { context.begin_path(); context.move_to(event.offset_x() as f64, event.offset_y() as f64); - *pressed.borrow_mut() = true; + pressed.set(true); }); (canvas.as_ref() as &web_sys::EventTarget) .add_event_listener_with_callback("mousedown", closure.as_ref().unchecked_ref()) @@ -50,7 +50,7 @@ pub fn main() { let context = context.clone(); let pressed = pressed.clone(); let closure: Closure = Closure::new(move |event: web_sys::MouseEvent| { - if *pressed.borrow() { + if pressed.get() { context.line_to(event.offset_x() as f64, event.offset_y() as f64); context.stroke(); context.begin_path(); @@ -66,7 +66,7 @@ pub fn main() { let context = context.clone(); let pressed = pressed.clone(); let closure: Closure = Closure::new(move |event: web_sys::MouseEvent| { - *pressed.borrow_mut() = false; + pressed.set(false); context.line_to(event.offset_x() as f64, event.offset_y() as f64); context.stroke(); });