Reorganize and rewrite examples

This commit is a large-ish scale reorganization of our examples. The
main goal here is to have a dedicated section of the guide for example,
and all examples will be listed there. Each example's `README` is now
just boilerplate pointing at the guide along with a blurb about how to
run it.

Some examples like `math` and `smorgasboard` have been deleted as they
didn't really serve much purpose, and others like `closures` have been
rewritten with `web-sys` instead of hand-bound bindings.

Overall it's hoped that this puts us in a good and consistent state for
our examples, with all of them being described in the guide, excerpts
are in the guide, and they're all relatively idiomatically using
`web-sys`.
This commit is contained in:
Alex Crichton
2018-09-20 16:20:42 -07:00
parent a85e49a2b4
commit 3efe51eb8b
128 changed files with 939 additions and 1304 deletions

View File

@ -1,27 +0,0 @@
use std::ops::Add;
#[derive(Clone, Copy, Debug)]
pub struct Complex {
pub real: f64,
pub imaginary: f64,
}
impl Complex {
pub fn square(self) -> Complex {
let real = (self.real * self.real) - (self.imaginary * self.imaginary);
let imaginary = 2.0 * self.real * self.imaginary;
Complex { real, imaginary }
}
pub fn norm(&self) -> f64 {
(self.real * self.real) + (self.imaginary * self.imaginary)
}
}
impl Add<Complex> for Complex {
type Output = Complex;
fn add(self, rhs: Complex) -> Complex {
Complex { real: self.real + rhs.real, imaginary: self.imaginary + rhs.imaginary }
}
}

View File

@ -1,36 +0,0 @@
pub mod complex;
use self::complex::Complex;
fn get_iter_index(z: Complex, c: Complex) -> u32 {
let mut iter_index: u32 = 0;
let mut z = z;
while iter_index < 900 {
if z.norm() > 2.0 {
break
}
z = z.square() + c;
iter_index += 1;
}
iter_index
}
pub fn get_julia_set(width: u32, height: u32, c: Complex) -> Vec<u8> {
let mut data: Vec<u8> = vec![];
let param_i = 1.5;
let param_r = 1.5;
let scale = 0.005;
for x in 0..width {
for y in 0..height {
let z = Complex { real: y as f64 * scale - param_r, imaginary: x as f64 * scale - param_i };
let iter_index = get_iter_index(z, c);
data.push((iter_index / 4) as u8);
data.push((iter_index / 2) as u8);
data.push(iter_index as u8);
data.push(255);
}
}
data
}

View File

@ -1,39 +1,115 @@
extern crate js_sys;
extern crate wasm_bindgen;
extern crate web_sys;
use std::ops::Add;
use wasm_bindgen::JsCast;
use wasm_bindgen::prelude::*;
use web_sys::CanvasRenderingContext2d;
use js_sys::{WebAssembly, Uint8ClampedArray};
mod fractal;
use fractal::get_julia_set;
use fractal::complex::Complex;
// Unfortunately `web-sys` at this time doesn't bind APIs with
// `Uint8ClampedArray`. For more information see rustwasm/wasm-bindgen#421.
//
// For now we just bind it ourselves and do some manual frobbing below.
#[wasm_bindgen]
extern "C" {
pub type ImageData;
type ImageData;
#[wasm_bindgen(constructor)]
pub fn new(arr: &Uint8ClampedArray, width: u32, height: u32) -> ImageData;
fn new(arr: &Uint8ClampedArray, width: u32, height: u32) -> ImageData;
}
#[wasm_bindgen]
extern "C" {
pub type Uint8ClampedArray;
#[wasm_bindgen(constructor)]
pub fn new(arr: &[u8]) -> Uint8ClampedArray;
}
#[wasm_bindgen]
extern "C" {
pub type CanvasRenderingContext2D;
#[wasm_bindgen(method, js_name = putImageData)]
pub fn put_image_data(this: &CanvasRenderingContext2D, image_data: &ImageData, p_1: i32, p_2: i32);
}
#[wasm_bindgen]
pub fn draw(ctx: &CanvasRenderingContext2D, width: u32, height: u32, real: f64, imaginary: f64) {
let c = Complex { real, imaginary };
pub fn draw(
ctx: &CanvasRenderingContext2d,
width: u32,
height: u32,
real: f64,
imaginary: f64,
) -> Result<(), JsValue> {
// The real workhorse of this algorithm, generating pixel data
let c = Complex { real, imaginary, };
let data = get_julia_set(width, height, c);
let uint8_array = Uint8ClampedArray::new(&data);
ctx.put_image_data(&ImageData::new(&uint8_array, width, height), 0, 0);
// And now that we've got some pixels, let's create an `ImageData` with the
// pixels and then ship it off to the canvas.
//
// See notes in the `wasm-in-wasm` example for why this is a bit dangerous
let my_memory = wasm_bindgen::memory()
.dyn_into::<WebAssembly::Memory>()
.unwrap();
let uint8_array = Uint8ClampedArray::new(&my_memory.buffer())
.subarray(
data.as_ptr() as u32,
data.as_ptr() as u32 + data.len() as u32,
);
let data = ImageData::new(&uint8_array, width, height);
ctx.put_image_data(data.unchecked_ref(), 0.0, 0.0)
}
fn get_julia_set(width: u32, height: u32, c: Complex) -> Vec<u8> {
let mut data = Vec::new();
let param_i = 1.5;
let param_r = 1.5;
let scale = 0.005;
for x in 0..width {
for y in 0..height {
let z = Complex {
real: y as f64 * scale - param_r,
imaginary: x as f64 * scale - param_i,
};
let iter_index = get_iter_index(z, c);
data.push((iter_index / 4) as u8);
data.push((iter_index / 2) as u8);
data.push(iter_index as u8);
data.push(255);
}
}
data
}
fn get_iter_index(z: Complex, c: Complex) -> u32 {
let mut iter_index: u32 = 0;
let mut z = z;
while iter_index < 900 {
if z.norm() > 2.0 {
break
}
z = z.square() + c;
iter_index += 1;
}
iter_index
}
#[derive(Clone, Copy, Debug)]
struct Complex {
real: f64,
imaginary: f64,
}
impl Complex {
fn square(self) -> Complex {
let real = (self.real * self.real) - (self.imaginary * self.imaginary);
let imaginary = 2.0 * self.real * self.imaginary;
Complex { real, imaginary }
}
fn norm(&self) -> f64 {
(self.real * self.real) + (self.imaginary * self.imaginary)
}
}
impl Add<Complex> for Complex {
type Output = Complex;
fn add(self, rhs: Complex) -> Complex {
Complex {
real: self.real + rhs.real,
imaginary: self.imaginary + rhs.imaginary,
}
}
}