Say, I have an array of float points (function xy). The first image is trying with SkiaSharp, the second is with System.Drawing of .NET Framework.
I understand that I should use a method like CubicTo, but I don't see how to combine it to achieve the expected result.
The example was created in WindowsForms (only uses 2 PictureBox) and SkiaSharp nuget. It is similar with Xamarin, the question is the same.
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using SkiaSharp;
namespace SKLab
{
public partial class BasicTestForm : Form
{
float startX = -4, stopX = 4;
float yi = -4, ye = 4;
float w = 200, h = 150;
float stepX = 1;
float x, px;
float y, py;
// pixel to cartesian
float pixelFromX(float cartX) => w * (cartX - startX) / (stopX - startX);
// cartesian to pixel
float pixelFromY(float cartY) => h * (cartY - yi) / (ye - yi);
public BasicTestForm()
{
InitializeComponent();
SkiaPlot(pictureBox1);
DrawingPlot(pictureBox2);
}
private void SkiaPlot(PictureBox p)
{
p.Size = new Size((int)w, (int)h);
using (var surface = SKSurface.Create(new SKImageInfo(p.Width, p.Height))) {
SKCanvas g = surface.Canvas;
g.Clear(SKColors.White);
using (var paint = new SKPaint()) {
paint.Style = SKPaintStyle.Stroke;
paint.IsAntialias = true;
paint.Color = SKColors.CornflowerBlue;
paint.StrokeWidth = 2;
var path = new SKPath();
for (x = startX; x <= stopX; x += stepX) {
px = pixelFromX(x);
py = pixelFromY((float)Math.Sin(x));
if (x == startX) {
path.MoveTo(px, py);
} else {
path.LineTo(px, py);
}
}
g.DrawPath(path, paint);
}
using (SKImage image = surface.Snapshot())
using (SKData data = image.Encode(SKEncodedImageFormat.Png, 100))
using (MemoryStream mStream = new MemoryStream(data.ToArray())) {
p.Image = new Bitmap(mStream, false);
}
}
}
void DrawingPlot(PictureBox p)
{
p.Size = new Size((int)w, (int)h); ;
// Make the Bitmap.
var canvas = new Bitmap(p.ClientSize.Width, p.ClientSize.Height);
using (var g = Graphics.FromImage(canvas)) {
// Clear.
g.Clear(Color.White);
// curve
var points = new List<PointF>();
for (x = startX; x <= stopX; x += stepX) {
points.Add(new PointF
{
X = pixelFromX(x),
Y = pixelFromY((float)Math.Sin(x))
});
}
g.SmoothingMode = SmoothingMode.AntiAlias;
using (var pen = new Pen(Color.CornflowerBlue, 2)) {
g.DrawCurve(pen, points.ToArray());
}
}
// Display the result.
p.Image = canvas;
}
}
}
Related
I have created wafermap chart. I want to make chips(die) in wafer selectable on mouse click and insert labels as well lines from one chip to another. Anyone expert in jfree chart?
wafermap chart
Here are the basic pieces for a tooltip listener for wafer maps, which is a form of selecting the die. Add the following to WaferMapPlot:
public String findChipAtPoint(double x, double y, Rectangle2D plotArea){
double[] xValues = this.getChipXValues(plotArea, dataset.getMaxChipX()
+ 2, dataset.getChipSpace());
double startX = xValues[1];
double chipWidth = xValues[0];
int ychips = this.dataset.getMaxChipY()+ 2;
double[] yValues = this.getChipYValues(plotArea, ychips,
dataset.getChipSpace());
double startY = yValues[1];
double chipHeight = yValues[0];
double chipSpace = dataset.getChipSpace();
int chipX = (int)Math.floor((x - startX + chipWidth + chipSpace) /
(chipWidth + chipSpace));
int chipY = (int)Math.floor((y - startY + chipHeight + chipSpace) /
(chipHeight + chipSpace));
chipX = chipX - dataset.getXOffset() - 1;
chipY = ychips - chipY - dataset.getYOffset() - 1;
StringBuilder sb = new StringBuilder("(");
Number value = dataset.getChipValue(chipX, chipY);
if (value instanceof Double)
value = value.intValue();
sb.append(chipX).append(",").append(chipY).append(") ").append(
(value == null) ? "" : value.toString());
return sb.toString();
}
Then make a subclass of ChartPanel that will be the listener:
public class WaferMapChartPanel extends ChartPanel {
WaferMapPlot waferPlot = null;
WaferMapDataset dataSet = null;
public WaferMapChartPanel(JFreeChart chart){
super(chart);
waferPlot = (WaferMapPlot)chart.getPlot();
if (waferPlot != null)
dataSet = waferPlot.getDataset();
}
/**
* Returns a string for the tooltip.
* #param e the mouse event.
* #return A tool tip or <code>null</code> if no tooltip is available.
*/
#Override
public String getToolTipText(MouseEvent e) {
if (waferPlot != null){
Object source = e.getSource();
if (source instanceof WaferMapChartPanel){
WaferMapChartPanel chartSource= (WaferMapChartPanel)e.getSource();
Rectangle2D plotArea = chartSource.getChartRenderingInfo().getPlotInfo().getPlotArea();
Insets insets = this.getInsets();
double x = (e.getX() - insets.left) / this.getScaleX();
double y = (e.getY() - insets.top) / this.getScaleY();
return waferPlot.findChipAtPoint(x, y, plotArea);
}
}
return "";
}
}
This creates a tooltip of the die's x,y and bin or whatever value you are using instead of bin.
I need to draw a custom image map of a park in my App and add show gps markers on it.
However my problem is that the map should be drawn as a straight rectangle in my app (see below left), but in real life the park is rotated (see example below right)
I have the GPS coordinates of all the 4 corners of the real-live map together with the GPS coordinates of the markers but i'm stuck on how to calculate the (x,y) position for each marker for the map in my app where the map is displayed as a straight rectangle.
Any suggestions are welcome!
Code i have so far:
public class GeoLocation
{
public double Lattitude { get; set; }
public double Longitude { get; set; }
public GeoLocation()
{
}
public GeoLocation(double lat, double lon)
{
Lattitude = lat;
Longitude = lon;
}
public double Angle(GeoLocation point)
{
var deltaX = point.Lattitude - Lattitude;
var deltaY = point.Longitude - Longitude;
return (Math.Atan2(deltaY, deltaX));
}
public GeoLocation Rotate(GeoLocation center, double angleInRad)
{
var s = Math.Sin(angleInRad);
var c = Math.Cos(angleInRad);
// translate point back to origin:
var x = (double)(Lattitude - center.Lattitude);
var y = (double)(Longitude - center.Longitude);
// rotate point
var xnew = x * c - y * s;
var ynew = x * s + y * c;
// translate point back:
x = xnew + center.Lattitude;
y = ynew + center.Longitude;
return new GeoLocation(x, y);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var url = "file://c:\\db\\mapgrab.jpg";
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(url, UriKind.Absolute);
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
mapImg.Source = bitmap;
var TopLeftGps = new GeoLocation(52.11070994543701, 4.411896866166349);
var TopRightGps = new GeoLocation(52.11475153599096, 4.415646979517055);
var BottomRightGps = new GeoLocation(52.1117075980591, 4.424232274309553);
var currentPosGps = new GeoLocation(52.11129692591393, 4.4174530542349295);
var imageWidth = 702;
var imageHeight = 924;
var angle = TopLeftGps.Angle(TopRightGps);
var topRight = TopRightGps.Rotate(TopLeftGps, -angle);
var bottomRight = BottomRightGps.Rotate(TopLeftGps, -angle);
var maxX = topRight.Lattitude - TopLeftGps.Lattitude;
var maxY = bottomRight.Longitude - topRight.Longitude;
var markerPos = new GeoLocation(currentPosGps.Lattitude, currentPosGps.Longitude).Rotate(TopLeftGps, -angle);
var diffX = markerPos.Lattitude - TopLeftGps.Lattitude;
var diffY = markerPos.Longitude - TopLeftGps.Longitude;
var percentageX = diffX / maxX;
var percentageY = diffY / maxY;
var posX = percentageX * imageWidth;
var posY = percentageY * imageHeight;
var markerImg = new Border();
markerImg.Background = new SolidColorBrush(Colors.Red);
markerImg.Width = 32;
markerImg.Height = 32;
Canvas.SetLeft(markerImg, posX);
Canvas.SetTop(markerImg, posY);
canvas.Children.Add(markerImg);
}
}
}
What you'r looking for is a 2D rotation transformation from the north aligned coordinates (x,y) to your rotated coordinates (x',y')
The rotation can be represented as a 2x2 matrix R and if we represent the coordinates as column vectors, then the computation will be:
[x',y']=R*[x,y]
Where * is matrix multiplication, R is
And the angle theta is the desired rotation angle.
Marking the corner points thus:
theta can be computed be solving (for example in wolframAlpha):
tan(theta) = (Ay-Dy) / (Ax-Dx)
I had a similar problem. Here is a javascript example how to rotate points on a map. The coordinates are measured from the center point. The angle is in radiants.
var x_new_centered = -1 * y_centered * Math.sin(a) + x_centered * Math.cos(a)
var y_new_centered = y_centered * Math.cos(a) + x_centered * Math.sin(a);
And here you find a jsfiddle where a point is drawn on a not rotated, a rotated and rotated and cropped map: https://jsfiddle.net/vienom/4ger35uq/
In my web application i need to draw shapes in the image using mouse.But i was struck draw and resize polygon..i have dawned polygon..How to resize it?
i can able to draw polygon using the above code.
But i need to resize it..any idea to resize the drowned polygon?
Please refer the below code.
private function onDrawTriangle() : void {
var ui:UIComponent = new UIComponent();
drawPanel = new Sprite();
drawPanel.graphics.clear();
drawPanel.graphics.lineStyle(2, 0xFF0000);
drawPanel.graphics.beginFill(0xDEFACE);
drawPanel.graphics.drawRect(0,0,300,300);
drawPanel.graphics.endFill();
ui.addChild(drawPanel);
addChild(ui);
ui.x = 20;
ui.y = 20;
_lineArr = new Array();
line = new Shape();
drawPanel.addEventListener(MouseEvent.CLICK,onAddPoint);
}
private function onAddPoint(evt:MouseEvent) : void {
if(numSpot <= 10) {
var point:Sprite = new Sprite();
point.graphics.clear();
point.graphics.lineStyle(0,0x0000FF);
point.graphics.beginFill(0x0000FF);
point.graphics.drawCircle(0,0,5);
point.graphics.endFill();
point.x = evt.localX;
point.y = evt.localY;
_lineArr.push({x:point.x,y:point.y});
drawPanel.addChild(point);
if(numSpot > 0) drawLine();
numSpot++;
}
}
private function drawLine() : void {
line.graphics.clear();
line.graphics.lineStyle(2,0x000000);
if(_lineArr.length > 2) line.graphics.beginFill(0xFF0000,0.5);
line.graphics.moveTo(_lineArr[0].x,_lineArr[0].y);
for(var i:int=1;i<_lineArr.length;i++) {
line.graphics.lineTo(_lineArr[i].x,_lineArr[i].y);
}
line.graphics.lineTo(_lineArr[0].x,_lineArr[0].y);
if(_lineArr.length > 2) line.graphics.endFill();
drawPanel.addChildAt(line,0);
}
Rather pushing points to array you may push the point(sprite variable).
Have a look on the modified codes for the above codes where I added some more events to re size the polygon
Here is the sample code:
private function onDrawTriangle() : void {
var ui:SpriteVisualElement = new SpriteVisualElement();
//ui.x = 20;
//ui.y = 20;
addElement(ui);
drawPanel = new Sprite();
drawPanel.graphics.clear();
drawPanel.graphics.lineStyle(2, 0xFF0000);
drawPanel.graphics.beginFill(0xDEFACE);
drawPanel.graphics.drawRect(0,0,300,300);
drawPanel.graphics.endFill();
ui.addChild(drawPanel);
_lineArr = new Array();
line = new Shape();
drawPanel.addEventListener(MouseEvent.CLICK,onAddPoint);
}
private function onAddPoint(evt:MouseEvent) : void {
if(numSpot <= 10) {
var point:Sprite = new Sprite();
point.graphics.clear();
point.graphics.lineStyle(0,0x0000FF);
point.graphics.beginFill(0x0000FF);
point.graphics.drawCircle(0,0,5);
point.graphics.endFill();
point.x = mouseX;
point.y = mouseY;
point.addEventListener(MouseEvent.MOUSE_DOWN , onDown);
_lineArr.push(point);
drawPanel.addChild(point);
if(numSpot > 0) drawLine();
numSpot++;
}
}
private function drawLine() : void {
line.graphics.clear();
line.graphics.lineStyle(2,0x000000);
if(_lineArr.length > 2) line.graphics.beginFill(0xFF0000,0.5);
line.graphics.moveTo(_lineArr[0].x,_lineArr[0].y);
for(var i:int=1;i<_lineArr.length;i++) {
line.graphics.lineTo(_lineArr[i].x,_lineArr[i].y);
}
line.graphics.lineTo(_lineArr[0].x,_lineArr[0].y);
if(_lineArr.length > 2) line.graphics.endFill();
drawPanel.addChildAt(line,0);
}
protected function onDown(event:MouseEvent):void
{
var point:Sprite = event.currentTarget as Sprite;
point.addEventListener(Event.ENTER_FRAME , onResize);
point.addEventListener(MouseEvent.MOUSE_UP , onUp);
drawPanel.removeEventListener(MouseEvent.CLICK,onAddPoint);
}
protected function onResize(event:Event):void
{
var point:Sprite = event.currentTarget as Sprite;
point.x = mouseX;
point.y = mouseY;
drawLine();
}
protected function onUp(event:MouseEvent):void
{
var point:Sprite = event.currentTarget as Sprite;
point.removeEventListener(Event.ENTER_FRAME , onResize);
point.removeEventListener(MouseEvent.MOUSE_UP , onUp);
drawPanel.addEventListener(MouseEvent.CLICK,onAddPoint);
}
I am using Open Flash Charts v2. I have been trying to make Conditional line graph. But I couldn't find any straight forward way, example or any class for producing Conditional charts.
Example of Conditional Graph
So I thought to use some techniques to emulate conditional graph ,I made separate Line object for values above limit range and then this line is used to overlap the plotted line.
This techniques works some what ok ,but there are problems with it,
How to color or place the conditional colored line exactly above the limit.
Remove tooltip and dot from limit line.
Tooltip of conditional line(red) and plotted line(green) are both shown ,I only need tooltip of green line.
Conditional Line Graph Problem illustrated
Source Code: // C#
var chart = new OpenFlashChart.OpenFlashChart();
var data1 = new List<double?> { 1, 3, 4, 5, 2, 1, 6, 7 };//>4=
var overlap = new List<double?> { null, null, 4, 5, null, null, null, null };
var overlap2 = new List<double?> { null, null, null, null, null, null, 6, 7 };
var limitData = new List<double?> { 4, 4, 4, 4, 4, 4, 4, 4 };
var line1 = new Line();
line1.Values = data1;
//line1.HaloSize = 0;
line1.Width = 2;
line1.DotSize = 5;
line1.DotStyleType.Tip = "#x_label#<br>#val#";
line1.Colour = "#37c855";
line1.Tooltip = "#val#";
var overLine = new Line();
overLine.Values = overlap;
//overLine.HaloSize = 0;
overLine.Width = 2;
overLine.DotSize = 5;
overLine.DotStyleType.Tip = "#x_label#<br>#val#";
overLine.Colour = "#d81417";
overLine.Tooltip = "#val#";
var overLine2 = new Line();
overLine2.Values = overlap2;
//overLine2.HaloSize = 0;
overLine2.Width = 2;
overLine2.DotSize = 5;
//overLine2.DotStyleType.Tip = "#x_label#<br>#val#";
//overLine2.DotStyleType.Type = DotType.DOT;
overLine2.Colour = "#d81417";
overLine2.Tooltip = "#val#";
var limit = new Line();
limit.Values = limitData;
limit.Width = 2;
limit.Colour = "#ff0000";
limit.HaloSize = -1;
limit.DotSize = -1;
// limit.DotStyleType.Tip = "";
limit.DotStyleType.Type = null;
//limit.Tooltip = "";
chart.AddElement(line1);
chart.AddElement(overLine);
chart.AddElement(overLine2);
chart.AddElement(limit);
chart.Y_Legend = new Legend("Experiment");
chart.Title = new Title("Conditional Line Graph");
chart.Y_Axis.SetRange(0, 10);
chart.X_Axis.Labels.Color = "#e43456";
chart.X_Axis.Steps = 4;
chart.Tooltip = new ToolTip("#val#");
chart.Tooltip.Shadow = true;
chart.Tooltip.Colour = "#e43456";
chart.Tooltip.MouseStyle = ToolTipStyle.CLOSEST;
Response.Clear();
Response.CacheControl = "no-cache";
Response.Write(chart.ToPrettyString());
Response.End();
Note:
I have already downloaded the OFC (Open Flash Charts) source ,If I modify the OFC Line.as source than how would I be able to generate json for the changed graph ? ,b/c I'm currently using .Net library for the json generation for OFC charts,please do let me know this also.
Update:
I have modified the source code on the advice of David Mears I'm using FlashDevelop for ActionScript.
P.S: I'm open for ideas if another library can do this job.
If you don't mind a little rebuilding, you can get the source of OFC here and modify the Line.solid_line() method in open-flash-chart/charts/Line.as to do this fairly easily.
In order to set the extra chart details through JSON using the .NET library, you'll also have to modify OpenFlashChart/LineBase.cs to add alternative colour and boundary properties. I'm not hugely familiar with .NET, but based on the existing properties you might add something like this:
private double boundary;
private string altcolour;
[JsonProperty("boundary")]
public virtual double Boundary
{
set { this.boundary = value; }
get { return this.boundary; }
}
[JsonProperty("alt-colour")]
public virtual string AltColour
{
set { this.altcolour = value; }
get { return this.altcolour; }
}
Then I believe the following should work in Line.as:
public function solid_line(): void {
var first:Boolean = true;
var i:Number;
var tmp:Sprite;
var x:Number;
var y:Number;
var last_e:Element;
var ratio:Number;
for ( i=0; i < this.numChildren; i++ ) {
// Step through every child object.
tmp = this.getChildAt(i) as Sprite;
// Only include data Elements, ignoring extra children such as line masks.
if( tmp is Element )
{
var e:Element = tmp as Element;
if( first )
{
if (this.props.get('alt-colour') != Number.NEGATIVE_INFINITY) {
if (e._y >= this.props.get_colour('boundary'))
{
// Line starts below boundary, set alt line colour.
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('alt-colour') );
}
else
{
// Line starts above boundary, set normal line colour.
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('colour') );
}
}
// Move to the first point.
this.graphics.moveTo(e.x, e.y);
x = e.x;
y = e.y;
first = false;
}
else
{
if (this.props.get('alt-colour') != Number.NEGATIVE_INFINITY) {
if (last_e._y < this.props.get_colour('boundary') && e._y >= this.props.get_colour('boundary'))
{
// Line passes below boundary. Draw first section and switch to alt colour.
ratio = (this.props.get_colour('boundary') - last_e._y) / (e._y - last_e._y);
this.graphics.lineTo(last_e.x + (e.x - last_e.x) * ratio, last_e.y + (e.y - last_e.y) * ratio);
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('alt-colour') );
}
else if (last_e._y >= this.props.get_colour('boundary') && e._y < this.props.get_colour('boundary'))
{
// Line passes above boundary. Draw first section and switch to normal colour.
ratio = (this.props.get_colour('boundary') - last_e._y) / (e._y - last_e._y);
this.graphics.lineTo(last_e.x + (e.x - last_e.x) * ratio, last_e.y + (e.y - last_e.y) * ratio);
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('colour') );
}
}
// Draw a line to the next point.
this.graphics.lineTo(e.x, e.y);
}
last_e = e;
}
}
if ( this.props.get('loop') ) {
// close the line loop (radar charts)
this.graphics.lineTo(x, y);
}
}
With the new open-flash-chart.swf, you should be able to just set your new properties on line1:
line1.Boundary = 4;
line1.AltColour = "#d81417";
After some search and reading the Graphics class document, I can't find a way to specify the line style of a line. I mean whether the line is a solid one or a dotted one. Could anybody help me?
Thanks!
You can't, well, not just by using Flex library classes anyway. You can do it yourself though, of course. Here's a class that implements it (modified from code found here, thanks Ken Fox):
/*Copyright (c) 2006 Adobe Systems Incorporated
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
package com.some.package {
import mx.graphics.IStroke;
import flash.display.Graphics;
public class GraphicsUtils {
public static function _drawDashedLine( target:Graphics, strokes:Array, pattern:Array,
drawingState:DashStruct,
x0:Number, y0:Number, x1:Number, y1:Number):void {
var dX:Number = x1 - x0;
var dY:Number = y1 - y0;
var len:Number = Math.sqrt( dX * dX + dY * dY );
dX /= len;
dY /= len;
var tMax:Number = len;
var t:Number = -drawingState.offset;
var patternIndex:int = drawingState.patternIndex;
var strokeIndex:int = drawingState.strokeIndex;
var styleInited:Boolean = drawingState.styleInited;
while( t < tMax ) {
t += pattern[patternIndex];
if( t < 0 ) {
var x:int = 5;
}
if( t >= tMax ) {
drawingState.offset = pattern[patternIndex] - ( t - tMax );
drawingState.patternIndex = patternIndex;
drawingState.strokeIndex = strokeIndex;
drawingState.styleInited = true;
t = tMax;
}
if( styleInited == false ) {
(strokes[strokeIndex] as IStroke).apply( target );
}
else {
styleInited = false;
}
target.lineTo( x0 + t * dX, y0 + t * dY );
patternIndex = ( patternIndex + 1 ) % pattern.length;
strokeIndex = ( strokeIndex + 1 ) % strokes.length;
}
}
public static function drawDashedLine( target:Graphics, strokes:Array, pattern:Array,
x0:Number, y0:Number, x1:Number, y1:Number ):void {
target.moveTo( x0, y0 );
var struct:DashStruct = new DashStruct();
_drawDashedLine( target, strokes, pattern, struct, x0, y0, x1, y1 );
}
public static function drawDashedPolyLine( target:Graphics, strokes:Array, pattern:Array,
points:Array ):void {
if( points.length == 0 ) { return; }
var prev:Object = points[0];
var struct:DashStruct = new DashStruct();
target.moveTo( prev.x, prev.y );
for( var i:int = 1; i < points.length; i++ ) {
var current:Object = points[i];
_drawDashedLine( target, strokes, pattern, struct,
prev.x, prev.y, current.x, current.y );
prev = current;
}
}
}
}
class DashStruct {
public function init():void {
patternIndex = 0;
strokeIndex = 0;
offset = 0;
}
public var patternIndex:int = 0;
public var strokeIndex:int = 0;
public var offset:Number = 0;
public var styleInited:Boolean = false;
}
And you can use it like:
var points:Array = [];
points.push( { x: 0, y: 0 } );
points.push( { x: this.width, y: 0 } );
points.push( { x: this.width, y: this.height } );
points.push( { x: 0, y: this.height } );
points.push( { x: 0, y: 0 } );
var strokes:Array = [];
var transparentStroke:Stroke = new Stroke( 0x0, 0, 0 );
strokes.push( new Stroke( 0x999999, 2, 1, false, 'normal', CapsStyle.NONE ) );
strokes.push( transparentStroke );
strokes.push( new Stroke( 0x222222, 2, 1, false, 'normal', CapsStyle.NONE ) );
strokes.push( transparentStroke );
GraphicsUtils.drawDashedPolyLine( this.graphics, strokes, [ 16, 5, 16, 5 ], points );
Well there is no Dashed or Dotted line in flex.
However, you can create your own line or border:
http://cookbooks.adobe.com/post_Creating_a_dashed_line_custom_border_with_dash_and-13286.html
Try and enjoy!
I ran across this, today, which I like a lot. Provides for dashed/dotted lines and a few other things (curves, primarily).
http://flexdevtips.blogspot.com/2010/01/drawing-dashed-lines-and-cubic-curves.html
I wrote some simple DashedLine code -
import flash.display.Graphics;
import spark.primitives.Line;
public class DashedLine extends Line
{
public var dashLength:Number = 10;
override protected function draw(g:Graphics):void
{
// Our bounding box is (x1, y1, x2, y2)
var x1:Number = measuredX + drawX;
var y1:Number = measuredY + drawY;
var x2:Number = measuredX + drawX + width;
var y2:Number = measuredY + drawY + height;
var isGap:Boolean;
// Which way should we draw the line?
if ((xFrom <= xTo) == (yFrom <= yTo))
{
// top-left to bottom-right
g.moveTo(x1, y1);
x1 += dashLength;
for(x1; x1 < x2; x1 += dashLength){
if(isGap){
g.moveTo(x1, y1);
} else {
g.lineTo(x1, y1);
}
isGap = !isGap;
}
}
else
{
// bottom-left to top-right
g.moveTo(x1, y2);
x1 += dashLength;
for(x1; x1 < x2; y2 += dashLength){
if(isGap){
g.moveTo(x1, y2);
} else {
g.lineTo(x1, y2);
}
isGap = !isGap;
}
}
}
}
Then use it like this -
<comps:DashedLine top="{}" left="0" width="110%" >
<comps:stroke>
<s:SolidColorStroke color="0xff0000" weight="1"/>
</comps:stroke>
</comps:DashedLine>
I do it pretty simple:
public static function drawDottedLine(target:Graphics, xFrom:Number, yFrom:Number, xTo:Number, yTo:Number, dotLenth:Number = 10):void{
var isGap:Boolean;
target.moveTo(xFrom, yFrom);
xFrom += dotLenth;
for(xFrom; xFrom < xTo; xFrom += dotLenth){
if(isGap){
target.moveTo(xFrom, yFrom);
} else {
target.lineTo(xFrom, yFrom);
}
isGap = !isGap;
}
}
UPD: :) The same way as in the link provided by Ross.