1
0
mirror of https://github.com/flutter/samples.git synced 2026-04-03 10:13:39 +00:00

Add flutter_web samples (#75)

This commit is contained in:
Kevin Moore
2019-05-07 13:32:08 -07:00
committed by Andrew Brogdon
parent 42f2dce01b
commit 3fe927cb29
697 changed files with 241026 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:math' show cos, pi, sin, Point;
import 'package:flutter_web/material.dart';
import 'package:charts_common/common.dart' as common show Color;
/// Draws a sector of a circle, with an optional hole in the center.
class CircleSectorPainter {
/// Draws a sector of a circle, with an optional hole in the center.
///
/// [center] The x, y coordinates of the circle's center.
/// [radius] The radius of the circle.
/// [innerRadius] Optional radius of a hole in the center of the circle that
/// should not be filled in as part of the sector.
/// [startAngle] The angle at which the arc starts, measured clockwise from
/// the positive x axis and expressed in radians.
/// [endAngle] The angle at which the arc ends, measured clockwise from the
/// positive x axis and expressed in radians.
/// [fill] Fill color for the sector.
/// [stroke] Stroke color of the arc and radius lines.
/// [strokeWidthPx] Stroke width of the arc and radius lines.
void draw(
{Canvas canvas,
Paint paint,
Point center,
double radius,
double innerRadius,
double startAngle,
double endAngle,
common.Color fill,
common.Color stroke,
double strokeWidthPx}) {
paint.color = new Color.fromARGB(fill.a, fill.r, fill.g, fill.b);
paint.style = PaintingStyle.fill;
final innerRadiusStartPoint = new Point<double>(
innerRadius * cos(startAngle) + center.x,
innerRadius * sin(startAngle) + center.y);
final innerRadiusEndPoint = new Point<double>(
innerRadius * cos(endAngle) + center.x,
innerRadius * sin(endAngle) + center.y);
final radiusStartPoint = new Point<double>(
radius * cos(startAngle) + center.x,
radius * sin(startAngle) + center.y);
final centerOffset = new Offset(center.x, center.y);
final isFullCircle = startAngle != null &&
endAngle != null &&
endAngle - startAngle == 2 * pi;
final midpointAngle = (endAngle + startAngle) / 2;
final path = new Path()
..moveTo(innerRadiusStartPoint.x, innerRadiusStartPoint.y);
path.lineTo(radiusStartPoint.x, radiusStartPoint.y);
// For full circles, draw the arc in two parts.
if (isFullCircle) {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: radius),
startAngle, midpointAngle - startAngle, true);
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: radius),
midpointAngle, endAngle - midpointAngle, true);
} else {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: radius),
startAngle, endAngle - startAngle, true);
}
path.lineTo(innerRadiusEndPoint.x, innerRadiusEndPoint.y);
// For full circles, draw the arc in two parts.
if (isFullCircle) {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: innerRadius),
endAngle, midpointAngle - endAngle, true);
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: innerRadius),
midpointAngle, startAngle - midpointAngle, true);
} else {
path.arcTo(new Rect.fromCircle(center: centerOffset, radius: innerRadius),
endAngle, startAngle - endAngle, true);
}
// Drawing two copies of this line segment, before and after the arcs,
// ensures that the path actually gets closed correctly.
path.lineTo(radiusStartPoint.x, radiusStartPoint.y);
canvas.drawPath(path, paint);
}
}

View File

@@ -0,0 +1,242 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter_web_ui/ui.dart' as ui show Shader;
import 'dart:math' show Point, Rectangle;
import 'package:flutter_web/material.dart';
import 'package:charts_common/common.dart' as common show Color;
/// Draws a simple line.
///
/// Lines may be styled with dash patterns similar to stroke-dasharray in SVG
/// path elements. Dash patterns are currently only supported between vertical
/// or horizontal line segments at this time.
class LinePainter {
/// Draws a simple line.
///
/// [dashPattern] controls the pattern of dashes and gaps in a line. It is a
/// list of lengths of alternating dashes and gaps. The rendering is similar
/// to stroke-dasharray in SVG path elements. An odd number of values in the
/// pattern will be repeated to derive an even number of values. "1,2,3" is
/// equivalent to "1,2,3,1,2,3."
void draw(
{Canvas canvas,
Paint paint,
List<Point> points,
Rectangle<num> clipBounds,
common.Color fill,
common.Color stroke,
bool roundEndCaps,
double strokeWidthPx,
List<int> dashPattern,
ui.Shader shader}) {
if (points.isEmpty) {
return;
}
// Apply clip bounds as a clip region.
if (clipBounds != null) {
canvas
..save()
..clipRect(new Rect.fromLTWH(
clipBounds.left.toDouble(),
clipBounds.top.toDouble(),
clipBounds.width.toDouble(),
clipBounds.height.toDouble()));
}
paint.color = new Color.fromARGB(stroke.a, stroke.r, stroke.g, stroke.b);
if (shader != null) {
paint.shader = shader;
}
// If the line has a single point, draw a circle.
if (points.length == 1) {
final point = points.first;
paint.style = PaintingStyle.fill;
canvas.drawCircle(new Offset(point.x, point.y), strokeWidthPx, paint);
} else {
if (strokeWidthPx != null) {
paint.strokeWidth = strokeWidthPx;
}
paint.strokeJoin = StrokeJoin.round;
paint.style = PaintingStyle.stroke;
if (dashPattern == null || dashPattern.isEmpty) {
if (roundEndCaps == true) {
paint.strokeCap = StrokeCap.round;
}
_drawSolidLine(canvas, paint, points);
} else {
_drawDashedLine(canvas, paint, points, dashPattern);
}
}
if (clipBounds != null) {
canvas.restore();
}
}
/// Draws solid lines between each point.
void _drawSolidLine(Canvas canvas, Paint paint, List<Point> points) {
// TODO: Extract a native line component which constructs the
// appropriate underlying data structures to avoid conversion.
final path = new Path()
..moveTo(points.first.x.toDouble(), points.first.y.toDouble());
for (var point in points) {
path.lineTo(point.x.toDouble(), point.y.toDouble());
}
canvas.drawPath(path, paint);
}
/// Draws dashed lines lines between each point.
void _drawDashedLine(
Canvas canvas, Paint paint, List<Point> points, List<int> dashPattern) {
final localDashPattern = new List.from(dashPattern);
// If an odd number of parts are defined, repeat the pattern to get an even
// number.
if (dashPattern.length % 2 == 1) {
localDashPattern.addAll(dashPattern);
}
// Stores the previous point in the series.
var previousSeriesPoint = _getOffset(points.first);
var remainder = 0;
var solid = true;
var dashPatternIndex = 0;
// Gets the next segment in the dash pattern, looping back to the
// beginning once the end has been reached.
var getNextDashPatternSegment = () {
final dashSegment = localDashPattern[dashPatternIndex];
dashPatternIndex = (dashPatternIndex + 1) % localDashPattern.length;
return dashSegment;
};
// Array of points that is used to draw a connecting path when only a
// partial dash pattern segment can be drawn in the remaining length of a
// line segment (between two defined points in the shape).
var remainderPoints;
// Draw the path through all the rest of the points in the series.
for (var pointIndex = 1; pointIndex < points.length; pointIndex++) {
// Stores the current point in the series.
final seriesPoint = _getOffset(points[pointIndex]);
if (previousSeriesPoint == seriesPoint) {
// Bypass dash pattern handling if the points are the same.
} else {
// Stores the previous point along the current series line segment where
// we rendered a dash (or left a gap).
var previousPoint = previousSeriesPoint;
var d = _getOffsetDistance(previousSeriesPoint, seriesPoint);
while (d > 0) {
var dashSegment =
remainder > 0 ? remainder : getNextDashPatternSegment();
remainder = 0;
// Create a unit vector in the direction from previous to next point.
final v = seriesPoint - previousPoint;
final u = new Offset(v.dx / v.distance, v.dy / v.distance);
// If the remaining distance is less than the length of the dash
// pattern segment, then cut off the pattern segment for this portion
// of the overall line.
final distance = d < dashSegment ? d : dashSegment.toDouble();
// Compute a vector representing the length of dash pattern segment to
// be drawn.
final nextPoint = previousPoint + (u * distance);
// If we are in a solid portion of the dash pattern, draw a line.
// Else, move on.
if (solid) {
if (remainderPoints != null) {
// If we had a partial un-drawn dash from the previous point along
// the line, draw a path that includes it and the end of the dash
// pattern segment in the current line segment.
remainderPoints.add(new Offset(nextPoint.dx, nextPoint.dy));
final path = new Path()
..moveTo(remainderPoints.first.dx, remainderPoints.first.dy);
for (var p in remainderPoints) {
path.lineTo(p.dx, p.dy);
}
canvas.drawPath(path, paint);
remainderPoints = null;
} else {
if (d < dashSegment && pointIndex < points.length - 1) {
// If the remaining distance d is too small to fit this dash,
// and we have more points in the line, save off a series of
// remainder points so that we can draw a path segment moving in
// the direction of the next point.
//
// Note that we don't need to save anything off for the "blank"
// portions of the pattern because we still take the remaining
// distance into account before starting the next dash in the
// next line segment.
remainderPoints = [
new Offset(previousPoint.dx, previousPoint.dy),
new Offset(nextPoint.dx, nextPoint.dy)
];
} else {
// Otherwise, draw a simple line segment for this dash.
canvas.drawLine(previousPoint, nextPoint, paint);
}
}
}
solid = !solid;
previousPoint = nextPoint;
d = d - dashSegment;
}
// Save off the remaining distance so that we can continue the dash (or
// gap) into the next line segment.
remainder = -d.round();
// If we have a remaining un-drawn distance for the current dash (or
// gap), revert the last change to "solid" so that we will continue
// either drawing a dash or leaving a gap.
if (remainder > 0) {
solid = !solid;
}
}
previousSeriesPoint = seriesPoint;
}
}
/// Converts a [Point] into an [Offset].
Offset _getOffset(Point point) =>
new Offset(point.x.toDouble(), point.y.toDouble());
/// Computes the distance between two [Offset]s, as if they were [Point]s.
num _getOffsetDistance(Offset o1, Offset o2) {
final p1 = new Point(o1.dx, o1.dy);
final p2 = new Point(o2.dx, o2.dy);
return p1.distanceTo(p2);
}
}

View File

@@ -0,0 +1,88 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:math' show cos, sin, Point;
import 'package:flutter_web/material.dart';
import 'package:charts_common/common.dart' as common show CanvasPie;
import 'circle_sector_painter.dart' show CircleSectorPainter;
/// Draws a pie chart, with an optional hole in the center.
class PiePainter {
CircleSectorPainter _circleSectorPainter;
/// Draws a pie chart, with an optional hole in the center.
void draw(Canvas canvas, Paint paint, common.CanvasPie canvasPie) {
_circleSectorPainter ??= new CircleSectorPainter();
final center = canvasPie.center;
final radius = canvasPie.radius;
final innerRadius = canvasPie.innerRadius;
for (var slice in canvasPie.slices) {
_circleSectorPainter.draw(
canvas: canvas,
paint: paint,
center: center,
radius: radius,
innerRadius: innerRadius,
startAngle: slice.startAngle,
endAngle: slice.endAngle,
fill: slice.fill);
}
// Draw stroke lines between pie slices. This is done after the slices are
// drawn to ensure that they appear on top.
if (canvasPie.stroke != null &&
canvasPie.strokeWidthPx != null &&
canvasPie.slices.length > 1) {
paint.color = new Color.fromARGB(canvasPie.stroke.a, canvasPie.stroke.r,
canvasPie.stroke.g, canvasPie.stroke.b);
paint.strokeWidth = canvasPie.strokeWidthPx;
paint.strokeJoin = StrokeJoin.bevel;
paint.style = PaintingStyle.stroke;
final path = new Path();
for (var slice in canvasPie.slices) {
final innerRadiusStartPoint = new Point<double>(
innerRadius * cos(slice.startAngle) + center.x,
innerRadius * sin(slice.startAngle) + center.y);
final innerRadiusEndPoint = new Point<double>(
innerRadius * cos(slice.endAngle) + center.x,
innerRadius * sin(slice.endAngle) + center.y);
final radiusStartPoint = new Point<double>(
radius * cos(slice.startAngle) + center.x,
radius * sin(slice.startAngle) + center.y);
final radiusEndPoint = new Point<double>(
radius * cos(slice.endAngle) + center.x,
radius * sin(slice.endAngle) + center.y);
path.moveTo(innerRadiusStartPoint.x, innerRadiusStartPoint.y);
path.lineTo(radiusStartPoint.x, radiusStartPoint.y);
path.moveTo(innerRadiusEndPoint.x, innerRadiusEndPoint.y);
path.lineTo(radiusEndPoint.x, radiusEndPoint.y);
}
canvas.drawPath(path, paint);
}
}
}

View File

@@ -0,0 +1,56 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:math' show Point;
import 'package:flutter_web/material.dart';
import 'package:charts_common/common.dart' as common show Color;
/// Draws a simple point.
///
/// TODO: Support for more shapes than circles?
class PointPainter {
void draw(
{Canvas canvas,
Paint paint,
Point point,
double radius,
common.Color fill,
common.Color stroke,
double strokeWidthPx}) {
if (point == null) {
return;
}
if (fill != null) {
paint.color = new Color.fromARGB(fill.a, fill.r, fill.g, fill.b);
paint.style = PaintingStyle.fill;
canvas.drawCircle(
new Offset(point.x.toDouble(), point.y.toDouble()), radius, paint);
}
// [Canvas.drawCircle] does not support drawing a circle with both a fill
// and a stroke at this time. Use a separate circle for the stroke.
if (stroke != null && strokeWidthPx != null && strokeWidthPx > 0.0) {
paint.color = new Color.fromARGB(stroke.a, stroke.r, stroke.g, stroke.b);
paint.strokeWidth = strokeWidthPx;
paint.strokeJoin = StrokeJoin.bevel;
paint.style = PaintingStyle.stroke;
canvas.drawCircle(
new Offset(point.x.toDouble(), point.y.toDouble()), radius, paint);
}
}
}

View File

@@ -0,0 +1,96 @@
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:math' show Point, Rectangle;
import 'package:flutter_web/material.dart';
import 'package:charts_common/common.dart' as common show Color;
/// Draws a simple line.
///
/// Lines may be styled with dash patterns similar to stroke-dasharray in SVG
/// path elements. Dash patterns are currently only supported between vertical
/// or horizontal line segments at this time.
class PolygonPainter {
/// Draws a simple line.
///
/// [dashPattern] controls the pattern of dashes and gaps in a line. It is a
/// list of lengths of alternating dashes and gaps. The rendering is similar
/// to stroke-dasharray in SVG path elements. An odd number of values in the
/// pattern will be repeated to derive an even number of values. "1,2,3" is
/// equivalent to "1,2,3,1,2,3."
void draw(
{Canvas canvas,
Paint paint,
List<Point> points,
Rectangle<num> clipBounds,
common.Color fill,
common.Color stroke,
double strokeWidthPx}) {
if (points.isEmpty) {
return;
}
// Apply clip bounds as a clip region.
if (clipBounds != null) {
canvas
..save()
..clipRect(new Rect.fromLTWH(
clipBounds.left.toDouble(),
clipBounds.top.toDouble(),
clipBounds.width.toDouble(),
clipBounds.height.toDouble()));
}
final strokeColor = stroke != null
? new Color.fromARGB(stroke.a, stroke.r, stroke.g, stroke.b)
: null;
final fillColor = fill != null
? new Color.fromARGB(fill.a, fill.r, fill.g, fill.b)
: null;
// If the line has a single point, draw a circle.
if (points.length == 1) {
final point = points.first;
paint.color = fillColor;
paint.style = PaintingStyle.fill;
canvas.drawCircle(new Offset(point.x, point.y), strokeWidthPx, paint);
} else {
if (strokeColor != null && strokeWidthPx != null) {
paint.strokeWidth = strokeWidthPx;
paint.strokeJoin = StrokeJoin.bevel;
paint.style = PaintingStyle.stroke;
}
if (fillColor != null) {
paint.color = fillColor;
paint.style = PaintingStyle.fill;
}
final path = new Path()
..moveTo(points.first.x.toDouble(), points.first.y.toDouble());
for (var point in points) {
path.lineTo(point.x.toDouble(), point.y.toDouble());
}
canvas.drawPath(path, paint);
}
if (clipBounds != null) {
canvas.restore();
}
}
}