diff --git a/libraries/bezier-rs/src/bezier/core.rs b/libraries/bezier-rs/src/bezier/core.rs index 2fb48d97..f528adae 100644 --- a/libraries/bezier-rs/src/bezier/core.rs +++ b/libraries/bezier-rs/src/bezier/core.rs @@ -177,10 +177,18 @@ impl Bezier { /// Appends to the `svg` mutable string with an SVG shape representation that includes the curve, the handle lines, the anchors, and the handles. pub fn to_svg(&self, svg: &mut String, curve_attributes: String, anchor_attributes: String, handle_attributes: String, handle_line_attributes: String) { - self.curve_to_svg(svg, curve_attributes); - self.handle_lines_to_svg(svg, handle_line_attributes); - self.anchors_to_svg(svg, anchor_attributes); - self.handles_to_svg(svg, handle_attributes); + if !curve_attributes.is_empty() { + self.curve_to_svg(svg, curve_attributes); + } + if !handle_line_attributes.is_empty() { + self.handle_lines_to_svg(svg, handle_line_attributes); + } + if !anchor_attributes.is_empty() { + self.anchors_to_svg(svg, anchor_attributes); + } + if !handle_attributes.is_empty() { + self.handles_to_svg(svg, handle_attributes); + } } /// Returns true if the corresponding points of the two `Bezier`s are within the provided absolute value difference from each other. diff --git a/website/other/bezier-rs-demos/src/App.vue b/website/other/bezier-rs-demos/src/App.vue index 285f8d22..279060ab 100644 --- a/website/other/bezier-rs-demos/src/App.vue +++ b/website/other/bezier-rs-demos/src/App.vue @@ -267,6 +267,27 @@ export default defineComponent({ }, }, }, + { + name: "Reduce", + callback: (bezier: WasmBezierInstance): string => bezier.reduce(), + }, + { + name: "Offset", + callback: (bezier: WasmBezierInstance, options: Record): string => bezier.offset(options.distance), + exampleOptions: { + [BezierCurveType.Quadratic]: { + sliderOptions: [ + { + variable: "distance", + min: -50, + max: 50, + step: 1, + default: 20, + }, + ], + }, + }, + }, ], features: [ { @@ -423,16 +444,6 @@ export default defineComponent({ }, curveDegrees: new Set([BezierCurveType.Cubic]), }, - { - name: "Reduce", - callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance): void => { - const context = getContextFromCanvas(canvas); - const curves: Point[][] = JSON.parse(bezier.reduce()); - curves.forEach((points, index) => { - drawBezier(context, points, null, { curveStrokeColor: `hsl(${40 * index}, 100%, 50%)`, radius: 3.5, drawHandles: false }); - }); - }, - }, { name: "Arcs", callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record): void => { @@ -484,34 +495,6 @@ export default defineComponent({ ], }, }, - { - name: "Offset", - callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record): void => { - const context = getContextFromCanvas(canvas); - const curves: Point[][] = JSON.parse(bezier.offset(options.distance)); - curves.forEach((points, index) => { - if (points.length === 2) { - drawLine(context, points[0], points[1], `hsl(${40 * index}, 100%, 50%)`); - } else { - drawCurve(context, points, `hsl(${40 * index}, 100%, 50%)`); - } - }); - drawPoint(context, curves[0][0], 4, "hsl(0, 100%, 50%)"); - drawPoint(context, curves[curves.length - 1][curves[0].length - 1], 4, `hsl(${40 * (curves.length - 1)}, 100%, 50%)`); - }, - template: markRaw(SliderExample), - templateOptions: { - sliders: [ - { - variable: "distance", - min: -50, - max: 50, - step: 1, - default: 20, - }, - ], - }, - }, ], subpathFeatures: [ { diff --git a/website/other/bezier-rs-demos/wasm/src/bezier.rs b/website/other/bezier-rs-demos/wasm/src/bezier.rs index 6edc7be8..2f09335b 100644 --- a/website/other/bezier-rs-demos/wasm/src/bezier.rs +++ b/website/other/bezier-rs-demos/wasm/src/bezier.rs @@ -396,15 +396,50 @@ impl WasmBezier { to_js_value(points) } - pub fn reduce(&self) -> JsValue { - let bezier_points: Vec> = self.0.reduce(None).into_iter().map(bezier_to_points).collect(); - to_js_value(bezier_points) + pub fn reduce(&self) -> String { + let empty_string = String::new(); + let original_curve_svg = self.get_bezier_path(); + let bezier_curves_svg: String = self + .0 + .reduce(None) + .iter() + .enumerate() + .map(|(idx, bezier_curve)| { + let mut curve_svg = String::new(); + bezier_curve.to_svg( + &mut curve_svg, + CURVE_ATTRIBUTES.to_string().replace(BLACK, &format!("hsl({}, 100%, 50%)", (40 * idx))), + empty_string.clone(), + empty_string.clone(), + empty_string.clone(), + ); + curve_svg + }) + .fold(original_curve_svg, |acc, item| format!("{acc}{item}")); + wrap_svg_tag(bezier_curves_svg) } - /// The wrapped return type is `Vec>`. - pub fn offset(&self, distance: f64) -> JsValue { - let bezier_points: Vec> = self.0.offset(distance).into_iter().map(bezier_to_points).collect(); - to_js_value(bezier_points) + pub fn offset(&self, distance: f64) -> String { + let empty_string = String::new(); + let original_curve_svg = self.get_bezier_path(); + let bezier_curves_svg = self + .0 + .offset(distance) + .iter() + .enumerate() + .map(|(idx, bezier_curve)| { + let mut curve_svg = String::new(); + bezier_curve.to_svg( + &mut curve_svg, + CURVE_ATTRIBUTES.to_string().replace(BLACK, &format!("hsl({}, 100%, 50%)", (40 * idx))), + empty_string.clone(), + empty_string.clone(), + empty_string.clone(), + ); + curve_svg + }) + .fold(original_curve_svg, |acc, item| format!("{acc}{item}")); + wrap_svg_tag(bezier_curves_svg) } /// The wrapped return type is `Vec`.