I am having some difficulty styling the HTML 5 Date input in Chrome.
Using mark up such as
<input type="date" max="2020-06-03" value="2020-06-01">, with some background and font color styling in CSS, renders in Chrome as:
I would like to make the calendar icon on the right hand side white, so it matches the color of the text.
::-webkit-calendar-picker-indicator looked like a possible candidate. Setting the background color on this changes the color behind the icon (as expected). However I can't find any parameter that has an effect on the icon color itself.
I've managed to work around it for now using a CSS filter to invert the black color to white
::-webkit-calendar-picker-indicator {
filter: invert(1);
}
However this feels quite fragile and far from ideal.
Another way, is by setting the "color-scheme" to dark.
input {
color-scheme: dark;
}
<input type="date" />
FYI: this will also put the popup in dark mode.
The Shadow DOM style sets a background-image which can not be interacted with in CSS (except for filter). One option is to replace the whole image where you can set any fill color and this method will be forward-compatible in case Chrome decides to inherit the icon color from color later on, at the cost of having a "hardcoded" icon:
::-webkit-calendar-picker-indicator {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" viewBox="0 0 24 24"><path fill="%23bbbbbb" d="M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z"/></svg>');
}
You can actually get rather creative using the filter property.
invert(100%) turns the icon white
brightness(50%) makes it gray
sepia(100%) saturates it and makes it... sepia
saturate(10000%) pumps the saturation up and turns it bright red
After that you can play around with hue-rotate to change the hue. hue-rotate(240deg) turns it blue, hue-rotate(120deg) turns it green etc. If you want to get a really specific color you should check out this question on how to transform black into any given color using only CSS filters.
Another example is;
input[type="date"]::-webkit-calendar-picker-indicator {
cursor: pointer;
border-radius: 4px;
margin-right: 2px;
opacity: 0.6;
filter: invert(0.8);
}
input[type="date"]::-webkit-calendar-picker-indicator:hover {
opacity: 1
}
I just found out about this awesome fiddle. You input the color you need in hex, and it gives you your filter code. Very pratical: https://codepen.io/sosuke/pen/Pjoqqp.
The javascript to calculate it is:
'use strict';
class Color {
constructor(r, g, b) {
this.set(r, g, b);
}
toString() {
return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)})`;
}
set(r, g, b) {
this.r = this.clamp(r);
this.g = this.clamp(g);
this.b = this.clamp(b);
}
hueRotate(angle = 0) {
angle = angle / 180 * Math.PI;
const sin = Math.sin(angle);
const cos = Math.cos(angle);
this.multiply([
0.213 + cos * 0.787 - sin * 0.213,
0.715 - cos * 0.715 - sin * 0.715,
0.072 - cos * 0.072 + sin * 0.928,
0.213 - cos * 0.213 + sin * 0.143,
0.715 + cos * 0.285 + sin * 0.140,
0.072 - cos * 0.072 - sin * 0.283,
0.213 - cos * 0.213 - sin * 0.787,
0.715 - cos * 0.715 + sin * 0.715,
0.072 + cos * 0.928 + sin * 0.072,
]);
}
grayscale(value = 1) {
this.multiply([
0.2126 + 0.7874 * (1 - value),
0.7152 - 0.7152 * (1 - value),
0.0722 - 0.0722 * (1 - value),
0.2126 - 0.2126 * (1 - value),
0.7152 + 0.2848 * (1 - value),
0.0722 - 0.0722 * (1 - value),
0.2126 - 0.2126 * (1 - value),
0.7152 - 0.7152 * (1 - value),
0.0722 + 0.9278 * (1 - value),
]);
}
sepia(value = 1) {
this.multiply([
0.393 + 0.607 * (1 - value),
0.769 - 0.769 * (1 - value),
0.189 - 0.189 * (1 - value),
0.349 - 0.349 * (1 - value),
0.686 + 0.314 * (1 - value),
0.168 - 0.168 * (1 - value),
0.272 - 0.272 * (1 - value),
0.534 - 0.534 * (1 - value),
0.131 + 0.869 * (1 - value),
]);
}
saturate(value = 1) {
this.multiply([
0.213 + 0.787 * value,
0.715 - 0.715 * value,
0.072 - 0.072 * value,
0.213 - 0.213 * value,
0.715 + 0.285 * value,
0.072 - 0.072 * value,
0.213 - 0.213 * value,
0.715 - 0.715 * value,
0.072 + 0.928 * value,
]);
}
multiply(matrix) {
const newR = this.clamp(this.r * matrix[0] + this.g * matrix[1] + this.b * matrix[2]);
const newG = this.clamp(this.r * matrix[3] + this.g * matrix[4] + this.b * matrix[5]);
const newB = this.clamp(this.r * matrix[6] + this.g * matrix[7] + this.b * matrix[8]);
this.r = newR;
this.g = newG;
this.b = newB;
}
brightness(value = 1) {
this.linear(value);
}
contrast(value = 1) {
this.linear(value, -(0.5 * value) + 0.5);
}
linear(slope = 1, intercept = 0) {
this.r = this.clamp(this.r * slope + intercept * 255);
this.g = this.clamp(this.g * slope + intercept * 255);
this.b = this.clamp(this.b * slope + intercept * 255);
}
invert(value = 1) {
this.r = this.clamp((value + this.r / 255 * (1 - 2 * value)) * 255);
this.g = this.clamp((value + this.g / 255 * (1 - 2 * value)) * 255);
this.b = this.clamp((value + this.b / 255 * (1 - 2 * value)) * 255);
}
hsl() {
// Code taken from https://stackoverflow.com/a/9493060/2688027, licensed under CC BY-SA.
const r = this.r / 255;
const g = this.g / 255;
const b = this.b / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {
h: h * 100,
s: s * 100,
l: l * 100,
};
}
clamp(value) {
if (value > 255) {
value = 255;
} else if (value < 0) {
value = 0;
}
return value;
}
}
class Solver {
constructor(target, baseColor) {
this.target = target;
this.targetHSL = target.hsl();
this.reusedColor = new Color(0, 0, 0);
}
solve() {
const result = this.solveNarrow(this.solveWide());
return {
values: result.values,
loss: result.loss,
filter: this.css(result.values),
};
}
solveWide() {
const A = 5;
const c = 15;
const a = [60, 180, 18000, 600, 1.2, 1.2];
let best = { loss: Infinity };
for (let i = 0; best.loss > 25 && i < 3; i++) {
const initial = [50, 20, 3750, 50, 100, 100];
const result = this.spsa(A, a, c, initial, 1000);
if (result.loss < best.loss) {
best = result;
}
}
return best;
}
solveNarrow(wide) {
const A = wide.loss;
const c = 2;
const A1 = A + 1;
const a = [0.25 * A1, 0.25 * A1, A1, 0.25 * A1, 0.2 * A1, 0.2 * A1];
return this.spsa(A, a, c, wide.values, 500);
}
spsa(A, a, c, values, iters) {
const alpha = 1;
const gamma = 0.16666666666666666;
let best = null;
let bestLoss = Infinity;
const deltas = new Array(6);
const highArgs = new Array(6);
const lowArgs = new Array(6);
for (let k = 0; k < iters; k++) {
const ck = c / Math.pow(k + 1, gamma);
for (let i = 0; i < 6; i++) {
deltas[i] = Math.random() > 0.5 ? 1 : -1;
highArgs[i] = values[i] + ck * deltas[i];
lowArgs[i] = values[i] - ck * deltas[i];
}
const lossDiff = this.loss(highArgs) - this.loss(lowArgs);
for (let i = 0; i < 6; i++) {
const g = lossDiff / (2 * ck) * deltas[i];
const ak = a[i] / Math.pow(A + k + 1, alpha);
values[i] = fix(values[i] - ak * g, i);
}
const loss = this.loss(values);
if (loss < bestLoss) {
best = values.slice(0);
bestLoss = loss;
}
}
return { values: best, loss: bestLoss };
function fix(value, idx) {
let max = 100;
if (idx === 2 /* saturate */) {
max = 7500;
} else if (idx === 4 /* brightness */ || idx === 5 /* contrast */) {
max = 200;
}
if (idx === 3 /* hue-rotate */) {
if (value > max) {
value %= max;
} else if (value < 0) {
value = max + value % max;
}
} else if (value < 0) {
value = 0;
} else if (value > max) {
value = max;
}
return value;
}
}
loss(filters) {
// Argument is array of percentages.
const color = this.reusedColor;
color.set(0, 0, 0);
color.invert(filters[0] / 100);
color.sepia(filters[1] / 100);
color.saturate(filters[2] / 100);
color.hueRotate(filters[3] * 3.6);
color.brightness(filters[4] / 100);
color.contrast(filters[5] / 100);
const colorHSL = color.hsl();
return (
Math.abs(color.r - this.target.r) +
Math.abs(color.g - this.target.g) +
Math.abs(color.b - this.target.b) +
Math.abs(colorHSL.h - this.targetHSL.h) +
Math.abs(colorHSL.s - this.targetHSL.s) +
Math.abs(colorHSL.l - this.targetHSL.l)
);
}
css(filters) {
function fmt(idx, multiplier = 1) {
return Math.round(filters[idx] * multiplier);
}
return `filter: invert(${fmt(0)}%) sepia(${fmt(1)}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(4)}%) contrast(${fmt(5)}%);`;
}
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, (m, r, g, b) => {
return r + r + g + g + b + b;
});
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16),
]
: null;
}
$(document).ready(() => {
$('button.execute').click(() => {
const rgb = hexToRgb($('input.target').val());
if (rgb.length !== 3) {
alert('Invalid format!');
return;
}
const color = new Color(rgb[0], rgb[1], rgb[2]);
const solver = new Solver(color);
const result = solver.solve();
let lossMsg;
if (result.loss < 1) {
lossMsg = 'This is a perfect result.';
} else if (result.loss < 5) {
lossMsg = 'The is close enough.';
} else if (result.loss < 15) {
lossMsg = 'The color is somewhat off. Consider running it again.';
} else {
lossMsg = 'The color is extremely off. Run it again!';
}
$('.realPixel').css('background-color', color.toString());
$('.filterPixel').attr('style', result.filter);
$('.filterDetail').text(result.filter);
$('.lossDetail').html(`Loss: ${result.loss.toFixed(1)}. <b>${lossMsg}</b>`);
});
});
input[type="date"]::-webkit-calendar-picker-indicator {
filter: invert(1);
margin: 0px;
margin-right: 20px !important; }
For posterity, check out this Codepen that transforms black into any color through the filter property
I want to draw a cylinder on canvas with control box to re size the cylinder.
Here's some javascript code I created to answer my own question:
function drawCylinder ( x, y, w, h ) {
context.beginPath(); //to draw the top circle
for (var i = 0 * Math.PI; i < 2 * Math.PI; i += 0.001) {
xPos = (this.x + this.w / 2) - (this.w / 2 * Math.sin(i)) *
Math.sin(0 * Math.PI) + (this.w / 2 * Math.cos(i)) *
Math.cos(0 * Math.PI);
yPos = (this.y + this.h / 8) + (this.h / 8 * Math.cos(i)) *
Math.sin(0 * Math.PI) + (this.h / 8 *
Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
}
else
{
context.lineTo(xPos, yPos);
}
}
context.moveTo(this.x, this.y + this.h / 8);
context.lineTo(this.x, this.y + this.h - this.h / 8);
for (var i = 0 * Math.PI; i < Math.PI; i += 0.001) {
xPos = (this.x + this.w / 2) - (this.w / 2 * Math.sin(i)) * Math.sin(0 * Math.PI) + (this.w / 2 * Math.cos(i)) * Math.cos(0 * Math.PI);
yPos = (this.y + this.h - this.h / 8) + (this.h / 8 * Math.cos(i)) * Math.sin(0 * Math.PI) + (this.h / 8 * Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
}
else
{
context.lineTo(xPos, yPos);
}
}
context.moveTo(this.x + this.w, this.y + this.h / 8);
context.lineTo(this.x + this.w, this.y + this.h - this.h / 8);
context.stroke();
}
Thank you! This is just what I was looking for. While implementing your function in my own code I made some changes like passing in the canvas context as an argument, simplifying the math and getting the code to pass JSLint.
function drawCylinder(ctx, x, y, w, h) {
'use strict';
var i, xPos, yPos, pi = Math.PI, twoPi = 2 * pi;
ctx.beginPath();
for (i = 0; i < twoPi; i += 0.001) {
xPos = (x + w / 2) - (w / 2 * Math.cos(i));
yPos = (y + h / 8) + (h / 8 * Math.sin(i));
if (i === 0) {
ctx.moveTo(xPos, yPos);
} else {
ctx.lineTo(xPos, yPos);
}
}
ctx.moveTo(x, y + h / 8);
ctx.lineTo(x, y + h - h / 8);
for (i = 0; i < pi; i += 0.001) {
xPos = (x + w / 2) - (w / 2 * Math.cos(i));
yPos = (y + h - h / 8) + (h / 8 * Math.sin(i));
if (i === 0) {
ctx.moveTo(xPos, yPos);
} else {
ctx.lineTo(xPos, yPos);
}
}
ctx.moveTo(x + w, y + h / 8);
ctx.lineTo(x + w, y + h - h / 8);
ctx.stroke();
}
If you want to draw a 3D cylinder, the easiest way is to use a library like tQuery (http://jeromeetienne.github.com/tquery/) :
var world = tQuery.createWorld().boilerplate().start();
var object = tQuery. createCylinder().addTo(world);
If you want to draw a '2d' cylinder, you can do so using canvas 2d API to draw a rectangle then a elipse in top of it. It will appear as a cylinder.
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
var pos={};
const angleToRadian = function (angle) {
return Math.PI / 180 * angle;
}
var Arc = function (x, y, r, d,s) {
this.r = r;
this.x = x;
this.y = y;
// this.d=d;
ctx.beginPath();
ctx.arc(x, y, r, angleToRadian(0), angleToRadian(180));
ctx.moveTo((Number(x) + Number(r)), y);
// ctx.lineTo((Number(x) + Number(r)), d);
ctx.arc(x, y - d, r, angleToRadian(0), angleToRadian(360));
ctx.moveTo((Number(x)+Number(r)),y);
ctx.lineTo((Number(x)+Number(lX())), ((Number(y)-Number(d))+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)+Number(lX())), ((Number(y)-Number(d))-Number(lY())+Number(r)));
ctx.lineTo((Number(x)+Number(lX())),(Number(y)+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)+Number(lX())),(Number(y)+Number(r)-Number(lY())));
ctx.lineTo(Number(x), ((Number(y)+Number(r))-Number(d)));
// ctx.moveTo(Number(x), ((Number(y)+Number(r))-Number(d)));
ctx.lineTo(Number(x),(Number(y)+Number(r)));
// ctx.moveTo(Number(x),(Number(y)+Number(r)));
ctx.lineTo((Number(x)-Number(lX())), (Number(y)-Number(d)+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)-Number(lX())), (Number(y)-Number(d)+Number(r)-Number(lY())));
ctx.lineTo((Number(x)-Number(lX())), (Number(y)+Number(r)-Number(lY())));
// ctx.moveTo((Number(x)-Number(lX())), (Number(y)+Number(r)-Number(lY())));
ctx.lineTo((Number(x)-Number(r)), (Number(y)-Number(d)));
// ctx.moveTo((Number(x)-Number(r)), (Number(y)-Number(d)));
ctx.lineTo((Number(x)-Number(r)), y);
ctx.strokeStyle = "#9c3028";
ctx.closePath();
// ctx.stroke();
ctx.fillStyle="#9b3028"
ctx.fill();
}
var lY = function () {
return Math.sqrt((Math.pow(((Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2) -
Math.pow((Math.cos(22.5 * Math.PI / 180) * (Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2)));
}
var lX = function () {
return Math.sqrt((Math.pow(((Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2) - (Math.pow(((Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2) -
Math.pow((Math.cos(22.5 * Math.PI / 180) * (Math.cos(67.5 * Math.PI / 180) * this.r) * 2), 2))));
}
document.addEventListener('mouseup',mouseUp);
document.addEventListener('mousedown',mouseDown);
document.addEventListener('mousemove',draw);
function mouseDown(e){
pos.x=e.clientX;
pos.y=e.clientY;
}
function mouseUp(e){
pos.pozX=e.clientX;
pos.pozY=e.clientY;
}
function draw(e){
if(e.buttons!==1) return;
ctx.clearRect(0,0,500,500);
Arc(pos.x, pos.y, e.clientY, e.clientX);
}
This is the full error message:
C:\Project Files\Good\src\views\RasterView.as(26): col: 39 Error: Type was not found or was not a compile-time constant: Raster.
C:\Project Files\Good\src\views\RasterView.as(42): col: 45 Error: Type was not found or was not a compile-time constant: Raster.
C:\Project Files\Good\src\views\RasterView.as(47): col: 45 Error: Type was not found or was not a compile-time constant: Raster.
C:\Project Files\Good\src\views\RasterView.as(62): col: 32 Error: Type was not found or was not a compile-time constant: Raster.
This is the file(it is huge)
package views
{
import flash.display.Bitmap;
import flash.geom.Point;
import views.Canvas.Raster;
/**
* ...
* #author Arthur Wulf White
*/
public class RasterView extends Bitmap
{
import views.Canvas.Raster
public static const SCHEMATIC : int = 1;
public static const SMOOTH : int = 2;
public static const RENDER_ONCE : int = 4;
public static const BOTH : int = SCHEMATIC + SMOOTH;
// protected var bitmapData : Raster;
protected var viewMode : int = 0;
protected var lineColor : int = 0xff000000;
protected var fillColor : int = 0xff808080;
protected var bgColor : int = 0xffffffff;
public function RasterView(raster : Raster)
{
this.bitmapData = raster;
}
public function getStyle():Vector.<int>
{
return new <int> [lineColor, fillColor, bgColor];
}
public function setStyle(lineColor : int, fillColor : int, bgColor : int):void
{
this.lineColor = lineColor;
this.fillColor = fillColor;
this.bgColor = bgColor;
}
public function backupView(backupRaster : Raster):void
{
backupRaster.copyPixels(bitmapData, bitmapData.rect, new Point());
}
public function loadBackup(backupRaster : Raster):void
{
bitmapData.copyPixels(backupRaster, backupRaster.rect, new Point());
}
public function getViewMode():int
{
return viewMode;
}
public function setViewMode(mode : int):void
{
viewMode = mode;
}
public function get Raster():Raster
{
return Raster(bitmapData);
}
public function refreshView():void
{
bitmapData.lock()
render();
bitmapData.unlock();
if ((getViewMode() & RENDER_ONCE) != 0)
{
setViewMode( getViewMode() ^ RENDER_ONCE);
}
}
public function render():void
{
}
protected function clear():void
{
bitmapData.fillRect(bitmapData.rect, bgColor);
}
}
}
This is the file for the Raster class(I don't think it is important for this issue)
/**
*
* Raster class
*
* #author Didier Brun aka Foxy - www.foxaweb.com
* #version 1.4
* #date 2006-01-06
* #link http://www.foxaweb.com
*
* AUTHORS ******************************************************************************
*
* authorName : Didier Brun - www.foxaweb.com
* contribution : the original class
* date : 2007-01-07
*
* authorName : Drew Cummins - http://blog.generalrelativity.org
* contribution : added bezier curves
* date : 2007-02-13
*
* authorName : Thibault Imbert - http://www.bytearray.org
* contribution : Raster now extends BitmapData, performance optimizations
* date : 2009-10-16
*
* PLEASE CONTRIBUTE ? http://www.bytearray.org/?p=67
*
* DESCRIPTION **************************************************************************
*
* Raster is an AS3 Bitmap drawing library. It provide some functions to draw directly
* into BitmapData instance.
*
* LICENSE ******************************************************************************
*
* This class is under RECIPROCAL PUBLIC LICENSE.
* http://www.opensource.org/licenses/rpl.php
*
* Please, keep this header and the list of all authors
*
*/
package views.Canvas
{
import flash.display.BitmapData;
import flash.display.Shape;
import flash.geom.Point;
import flash.geom.Rectangle;
public class Raster extends BitmapData
{
private var shape : Shape = new Shape();
private var buffer:Array = new Array();
private var r:Rectangle = new Rectangle();
public function Raster ( width:uint, height:uint, transparent:Boolean=false, color:uint=0)
{
super ( width, height, transparent, color);
}
// ------------------------------------------------
//
// ---o public methods
//
// ------------------------------------------------
public function setPoint( p : Point, color : int, size : int = 1):void
{
if(size == 1)
setPixel(p.x, p.y, color);
else if (size > 1)
drawRect(new Rectangle(p.x - size / 2, p.y - size / 2, size, size), color);
}
public function lineAA( x0:int, y0:int, x1:int, y1:int, color:uint ):void
{
var i : int = 0;
var cInt : int;
var cNum : Number;
var div : Number;
var dx : int = Math.abs(x1 - x0);
var dy : int = Math.abs(y1 - y0);
if(dx >= dy)
{
//do x
if (x0 < x1)
{
cInt = x0;
cNum = y0;
}
else
{
cInt = x1;
cNum = y1;
}
div = Number(y1 - y0) / Number(x1 - x0);
setPixel32(cInt, cNum, color);
for (; i <= dx; i++)
{
cInt++;
cNum += div;
setAAPixel(cInt, cNum, color, true, false);
}
}
else
{
//do y
if (y0 < y1)
{
cInt = y0;
cNum = x0;
}
else
{
cInt = y1;
cNum = x1;
}
div = Number(x1 - x0) / Number(y1 - y0);
setPixel32(cNum, cInt, color);
for (; i <= dy; i++)
{
cInt++;
cNum += div;
setAAPixel(cNum, cInt, color, false, true);
}
}
}
public function quadLine(x0 : int, y0 : int, cx : int, cy : int, x1 : int, y1 : int, color : int = 0xff0000ff, detail : int = 20):void
{
var epsilon : Number = 1.0 / Number(detail);
var total : Number = 0;
var x : int = 0;
var y : int = 0;
for (; total <= 1.001; total+=epsilon)
{
x = (1 - total) * ((1 - total) * x0 + total * cx) + total * (total * x1 + (1 - total) * cx);
y = (1 - total) * ((1 - total) * y0 + total * cy) + total * (total * y1 + (1 - total) * cy);
setPixel32(x, y, color);
}
}
/**
* Draws a antialias Quadratic Bezier Curve (equivalent to a DisplayObject's graphics#curveTo)
*
* #param x0 x position of first anchor
* #param y0 y position of first anchor
* #param x1 x position of control point
* #param y1 y position of control point
* #param x2 x position of second anchor
* #param y2 y position of second anchor
* #param c color
* #param resolution [optional] determines the accuracy of the curve's length (higher number = greater accuracy = longer process)
* */
public function aaQuadBezier ( anchorX0:int, anchorY0:int, controlX:int, controlY:int, anchorX1:int, anchorY1:int, c:Number, resolution:int = 3):void
{
shape.graphics.clear();
shape.graphics.lineStyle(1, c, 1);
shape.graphics.moveTo(anchorX0, anchorY0);
shape.graphics.curveTo(controlX, controlY, anchorX1, anchorY1);
this.draw(shape);
}
/**
* Draw an anti-aliased line
*
* #param x0 first point x coord
* #param y0 first point y coord
* #param x1 second point x coord
* #param y1 second point y coord
* #param c color (0xaarrvvbb)
*/
public function aaLine2( x1:int, y1:int, x2:int, y2:int, color:uint ):void
{
shape.graphics.clear();
shape.graphics.lineStyle(1, color, 1);
shape.graphics.moveTo(x1, y1);
shape.graphics.lineTo(x2, y2);
this.draw(shape);
}
/**
* Draw a line
*
* #param x0 first point x coord
* #param y0 first point y coord
* #param x1 second point x coord
* #param y1 second point y coord
* #param c color (0xaarrvvbb)
*/
public function line ( x0:int, y0:int, x1:int, y1:int, color:uint ):void
{
var dx:int;
var dy:int;
var i:int;
var xinc:int;
var yinc:int;
var cumul:int;
var x:int;
var y:int;
x = x0;
y = y0;
dx = x1 - x0;
dy = y1 - y0;
xinc = ( dx > 0 ) ? 1 : -1;
yinc = ( dy > 0 ) ? 1 : -1;
dx = dx < 0 ? -dx : dx;
dy = dy < 0 ? -dy : dy;
setPixel32(x,y,color);
if ( dx > dy )
{
cumul = dx >> 1;
for ( i = 1 ; i <= dx ; ++i )
{
x += xinc;
cumul += dy;
if (cumul >= dx)
{
cumul -= dx;
y += yinc;
}
setPixel32(x,y,color);
}
}else
{
cumul = dy >> 1;
for ( i = 1 ; i <= dy ; ++i )
{
y += yinc;
cumul += dx;
if ( cumul >= dy )
{
cumul -= dy;
x += xinc ;
}
setPixel32(x,y,color);
}
}
}
/**
* Draw a triangle
*
* #param x0 first point x coord
* #param y0 first point y coord
* #param x1 second point x coord
* #param y1 second point y coord
* #param x2 third point x coord
* #param y2 third point y coord
* #param c color (0xaarrvvbb)
*/
public function triangle ( x0:int, y0:int, x1:int, y1:int, x2:int, y2:int, color:uint ):void
{
line (x0,y0,x1,y1,color);
line (x1,y1,x2,y2,color);
line (x2,y2,x0,y0,color);
}
/**
* Draw a filled triangle
*
* #param x0 first point x coord
* #param y0 first point y coord
* #param x1 second point x coord
* #param y1 second point y coord
* #param x2 third point x coord
* #param y2 third point y coord
* #param c color (0xaarrvvbb)
*/
public function filledTri ( x0:int, y0:int, x1:int, y1:int, x2:int, y2:int, color:uint ):void
{
buffer.length = 0;
lineTri (buffer,x0,y0,x1,y1,color);
lineTri (buffer,x1,y1,x2,y2,color);
lineTri (buffer,x2,y2,x0,y0,color);
}
/**
* Draw a circle
*
* #param px first point x coord
* #param py first point y coord
* #param r radius
* #param c color (0xaarrvvbb)
*/
public function circle ( px:int, py:int, r:int, color:uint ):void
{
var x:int;
var y:int;
var d:int;
x = 0;
y = r;
d = 1-r;
setPixel32(px+x,py+y,color);
setPixel32(px+x,py-y,color);
setPixel32(px-y,py+x,color);
setPixel32(px+y,py+x,color);
while ( y > x )
{
if ( d < 0 )
{
d += (x+3) << 1;
}else
{
d += ((x - y) << 1) + 5;
y--;
}
x++;
setPixel32(px+x,py+y,color);
setPixel32(px-x,py+y,color);
setPixel32(px+x,py-y,color);
setPixel32(px-x,py-y,color);
setPixel32(px-y,py+x,color);
setPixel32(px-y,py-x,color);
setPixel32(px+y,py-x,color);
setPixel32(px+y,py+x,color);
}
}
/**
* Draw an anti-aliased circle
*
* #param px first point x coord
* #param py first point y coord
* #param r radius
* #param c color (0xaarrvvbb)
*/
public function aaCircle ( px:int, py:int, r:int, color:uint ):void
{
var vx:int;
var vy:int;
var d:int;
vx = r;
vy = 0;
var t:Number=0;
var dry:Number;
var buff:int;
setPixel(px+vx,py+vy,color);
setPixel(px-vx,py+vy,color);
setPixel(px+vy,py+vx,color);
setPixel(px+vy,py-vx,color);
while ( vx > vy+1 )
{
vy++;
buff = Math.sqrt(r*r-vy*vy)+1;
dry = buff - Math.sqrt(r*r-vy*vy);
if (dry<t) vx--;
drawAlphaPixel(px+vx,py+vy,1-dry,color)
drawAlphaPixel(px+vx-1,py+vy,dry,color)
drawAlphaPixel(px-vx,py+vy,1-dry,color)
drawAlphaPixel(px-vx+1,py+vy,dry,color)
drawAlphaPixel(px+vx,py-vy,1-dry,color)
drawAlphaPixel(px+vx-1,py-vy,dry,color)
drawAlphaPixel(px-vx,py-vy,1-dry,color)
drawAlphaPixel(px-vx+1,py-vy,dry,color)
drawAlphaPixel(px+vy,py+vx,1-dry,color)
drawAlphaPixel(px+vy,py+vx-1,dry,color)
drawAlphaPixel(px-vy,py+vx,1-dry,color)
drawAlphaPixel(px-vy,py+vx-1,dry,color)
drawAlphaPixel(px+vy,py-vx,1-dry,color)
drawAlphaPixel(px+vy,py-vx+1,dry,color)
drawAlphaPixel(px-vy,py-vx,1-dry,color)
drawAlphaPixel(px-vy,py-vx+1,dry,color)
t=dry;
}
}
/**
* Draw an anti-aliased line
*
* #param x0 first point x coord
* #param y0 first point y coord
* #param x1 second point x coord
* #param y1 second point y coord
* #param c color (0xaarrvvbb)
*/
public function aaLine ( x1:int, y1:int, x2:int, y2:int, color:uint ):void
{
var steep:Boolean = Math.abs(y2 - y1) > Math.abs(x2 - x1);
var swap:int;
if (steep)
{
swap=x1; x1=y1; y1=swap;
swap=x2; x2=y2; y2=swap;
}
if (x1 > x2)
{
swap=x1; x1=x2; x2=swap;
swap=y1; y1=y2; y2=swap;
}
var dx:int = x2 - x1;
var dy:int = y2 - y1
var gradient:Number = dy / dx;
var xend:int = x1;
var yend:Number = y1 + gradient * (xend - x1);
var xgap:Number = 1-((x1 + 0.5)%1);
var xpx1:int = xend;
var ypx1:int = yend;
var alpha:Number;
alpha = ((yend)%1) * xgap;
var intery:Number = yend + gradient;
xend = x2;
yend = y2 + gradient * (xend - x2)
xgap = (x2 + 0.5)%1;
var xpx2:int = xend;
var ypx2:int = yend;
alpha = (1-((yend)%1)) * xgap;
if (steep)
drawAlphaPixel(ypx2,xpx2,alpha,color);
else drawAlphaPixel(xpx2, ypx2,alpha,color);
alpha = ((yend)%1) * xgap;
if (steep)
drawAlphaPixel(ypx2 + 1,xpx2,alpha,color);
else drawAlphaPixel(xpx2, ypx2 + 1,alpha,color);
var x:int=xpx1;
while (x++<xpx2)
{
alpha = 1-((intery)%1);
if (steep)
drawAlphaPixel(intery,x,alpha,color);
else drawAlphaPixel(x,intery,alpha,color);
alpha=intery%1;
if (steep)
drawAlphaPixel(intery+1,x,alpha,color);
else drawAlphaPixel(x,intery+1,alpha,color);
intery = intery + gradient
}
}
/**
* Draws a Rectangle
*
* #param rect Rectangle dimensions
* #param color color
* */
public function drawRect ( rect:Rectangle, color:uint ):void
{
line ( rect.x, rect.y, rect.x+rect.width, rect.y, color );
line ( rect.x+rect.width, rect.y, rect.x+rect.width, rect.y+rect.height, color );
line ( rect.x+rect.width, rect.y+rect.height, rect.x, rect.y+rect.height, color );
line ( rect.x, rect.y+rect.height, rect.x, rect.y, color );
}
/**
* Draws a rounded Rectangle
*
* #param rect Rectangle dimensions
* #param ellipseWidth Rectangle corners width
* #param color color
* */
public function drawRoundRect ( rect:Rectangle, ellipseWidth:int, color:uint ):void
{
var arc:Number = 4/3 * (Math.sqrt(2) - 1);
var xc:Number = rect.x+rect.width-ellipseWidth;
var yc:Number = rect.y+ellipseWidth;
line( rect.x+ellipseWidth, rect.y, xc, rect.y, color );
cubicBezier(xc, rect.y, xc + ellipseWidth*arc, yc - ellipseWidth, xc + ellipseWidth, yc - ellipseWidth*arc, xc + ellipseWidth, yc, color);
xc = rect.x+rect.width-ellipseWidth;
yc = rect.y+rect.height-ellipseWidth;
line( xc + ellipseWidth, rect.y+ellipseWidth, rect.x+rect.width, yc, color );
cubicBezier(rect.x+rect.width, yc, xc + ellipseWidth, yc + ellipseWidth*arc, xc + ellipseWidth*arc, yc + ellipseWidth, xc, yc + ellipseWidth, color);
xc = rect.x+ellipseWidth;
yc = rect.y+rect.height-ellipseWidth;
line( rect.x+rect.width-ellipseWidth, rect.y+rect.height, xc, yc + ellipseWidth, color );
cubicBezier( xc, yc + ellipseWidth, xc - ellipseWidth*arc, yc + ellipseWidth, xc - ellipseWidth, yc + ellipseWidth*arc, xc - ellipseWidth, yc, color );
xc = rect.x+ellipseWidth;
yc = rect.y+ellipseWidth;
line( xc - ellipseWidth, rect.y+rect.height-ellipseWidth, rect.x, yc, color );
cubicBezier(rect.x, yc, xc - ellipseWidth, yc - ellipseWidth*arc, xc - ellipseWidth*arc, yc - ellipseWidth, xc, yc - ellipseWidth, color);
}
/**
* Draws a Quadratic Bezier Curve (equivalent to a DisplayObject's graphics#curveTo)
*
* #param x0 x position of first anchor
* #param y0 y position of first anchor
* #param x1 x position of control point
* #param y1 y position of control point
* #param x2 x position of second anchor
* #param y2 y position of second anchor
* #param c color
* #param resolution [optional] determines the accuracy of the curve's length (higher number = greater accuracy = longer process)
* */
public function quadBezier ( anchorX0:int, anchorY0:int, controlX:int, controlY:int, anchorX1:int, anchorY1:int, c:Number, resolution:int = 3):void
{
var ox:Number = anchorX0;
var oy:Number = anchorY0;
var px:int;
var py:int;
var dist:Number = 0;
var inverse:Number = 1 / resolution;
var interval:Number;
var intervalSq:Number;
var diff:Number;
var diffSq:Number;
var i:int = 0;
while( ++i <= resolution )
{
interval = inverse * i;
intervalSq = interval * interval;
diff = 1 - interval;
diffSq = diff * diff;
px = diffSq * anchorX0 + 2 * interval * diff * controlX + intervalSq * anchorX1;
py = diffSq * anchorY0 + 2 * interval * diff * controlY + intervalSq * anchorY1;
dist += Math.sqrt( ( px - ox ) * ( px - ox ) + ( py - oy ) * ( py - oy ) );
ox = px;
oy = py;
}
//approximates the length of the curve
var curveLength:int = dist;
inverse = 1 / curveLength;
var lastx:int=anchorX0;
var lasty:int=anchorY0;
i = -1;
while( ++i <= curveLength )
{
interval = inverse * i;
intervalSq = interval * interval;
diff = 1 - interval;
diffSq = diff * diff;
px = diffSq * anchorX0 + 2 * interval * diff * controlX + intervalSq * anchorX1;
py = diffSq * anchorY0 + 2 * interval * diff * controlY + intervalSq * anchorY1;
line(lastx,lasty,px,py,c);
//aaLine(lastx, lasty, px, py, c);
lastx = px;
lasty = py;
}
}
/**
* Draws a Cubic Bezier Curve
*
* TODO: Determine whether x/y params would be better named as anchor/control
*
* #param x0 x position of first anchor
* #param y0 y position of first anchor
* #param x1 x position of control point
* #param y1 y position of control point
* #param x2 x position of second control point
* #param y2 y position of second control point
* #param x3 x position of second anchor
* #param y3 y position of second anchor
* #param c color
* #param resolution [optional] determines the accuracy of the curve's length (higher number = greater accuracy = longer process)
* */
public function cubicBezier ( x0:int, y0:int, x1:int, y1:int, x2:int, y2:int, x3:int, y3:int, c:Number, resolution:int = 5 ):void
{
var ox:Number = x0;
var oy:Number = y0;
var px:int;
var py:int;
var dist:Number = 0;
var inverse:Number = 1 / resolution;
var interval:Number;
var intervalSq:Number;
var intervalCu:Number;
var diff:Number;
var diffSq:Number;
var diffCu:Number;
var i:int = 0;
while( ++i <= resolution )
{
interval = inverse * i;
intervalSq = interval * interval;
intervalCu = intervalSq * interval;
diff = 1 - interval;
diffSq = diff * diff;
diffCu = diffSq * diff;
px = diffCu * x0 + 3 * interval * diffSq * x1 + 3 * x2 * intervalSq * diff + x3 * intervalCu;
py = diffCu * y0 + 3 * interval * diffSq * y1 + 3 * y2 * intervalSq * diff + y3 * intervalCu;
dist += Math.sqrt( ( px - ox ) * ( px - ox ) + ( py - oy ) * ( py - oy ) );
ox = px;
oy = py;
}
//approximates the length of the curve
var curveLength:int = dist;
inverse = 1 / curveLength;
var lastx:int=x0;
var lasty:int=y0;
i = -1;
while( ++i <= curveLength )
{
interval = inverse * i;
intervalSq = interval * interval;
intervalCu = intervalSq * interval;
diff = 1 - interval;
diffSq = diff * diff;
diffCu = diffSq * diff;
px = diffCu * x0 + 3 * interval * diffSq * x1 + 3 * x2 * intervalSq * diff + x3 * intervalCu;
py = diffCu * y0 + 3 * interval * diffSq * y1 + 3 * y2 * intervalSq * diff + y3 * intervalCu;
line(lastx,lasty,px,py,c);
lastx = px;
lasty = py;
}
}
// ------------------------------------------------
//
// ---o private static methods
//
// ------------------------------------------------
/**
* Draw an AA pixel
*/
private function setAAPixel (x:Number, y:Number, c:Number, roundX : Boolean = false, roundY : Boolean = false):void
{
var xpos : Number = Math.floor(x);
var ypos : Number = Math.floor(y);
var xA : Number = x - xpos;
var yA : Number = y - ypos;
if (!roundX && !roundY)
{
drawAlphaPixel(xpos , ypos , (1 - xA) * (1 - yA) , c);
drawAlphaPixel(xpos + 1 , ypos , xA * (1 - yA) , c);
drawAlphaPixel(xpos , ypos + 1 , (1 - xA) * yA , c);
drawAlphaPixel(xpos + 1 , ypos + 1 , xA * yA , c);
}
else if (roundX && !roundY)
{
drawAlphaPixel(xpos , ypos , (1 - yA) , c);
drawAlphaPixel(xpos , ypos + 1 , yA , c);
}
else if (roundY && !roundX)
{
drawAlphaPixel(xpos , ypos , (1 - xA) , c);
drawAlphaPixel(xpos + 1 , ypos , xA , c);
}
else if (roundX && roundY)
{
setPixel32(xpos , ypos , c);
}
}
/**
* Draw an alpha32 pixel
*/
private function drawAlphaPixel ( x:int, y:int, a:Number, c:Number, bg : int = -1 ):void
{
//var g:uint = getPixel32(x,y);
var g : int = 0xff000000;
var r0:uint = ((g & 0x00FF0000) >> 16);
var g0:uint = ((g & 0x0000FF00) >> 8);
var b0:uint = ((g & 0x000000FF));
var r1:uint = ((c & 0x00FF0000) >> 16);
var g1:uint = ((c & 0x0000FF00) >> 8);
var b1:uint = ((c & 0x000000FF));
var ac:Number = 0xFF;
var rc:Number = r1*a+r0*(1-a);
var gc:Number = g1*a+g0*(1-a);
var bc:Number = b1*a+b0*(1-a);
var n:uint = (ac<<24)+(rc<<16)+(gc<<8)+bc;
setPixel32(x,y,n);
}
/**
* Check a triangle line
*/
private function checkLine ( o:Array, x:int, y:int, c:int, r:Rectangle ):void
{
if (o[y])
{
if (o[y]>x)
{
r.width=o[y]-x;
r.x=x;
r.y=y;
fillRect(r,c);
}else
{
r.width=x-o[y];
r.x=o[y];
r.y=y;
fillRect(r,c);
}
}else
{
o[y]=x;
}
}
/**
* Special line for filled triangle
*/
private function lineTri ( o:Array, x0:int, y0:int, x1:int, y1:int, c:Number ):void
{
var steep:Boolean= (y1-y0)*(y1-y0) > (x1-x0)*(x1-x0);
var swap:int;
if (steep)
{
swap=x0; x0=y0; y0=swap;
swap=x1; x1=y1; y1=swap;
}
if (x0>x1)
{
x0^=x1; x1^=x0; x0^=x1;
y0^=y1; y1^=y0; y0^=y1;
}
var deltax:int = x1 - x0
var deltay:int = (y1 - y0) < 0 ? -(y1 - y0) : (y1 - y0);
var error:int = 0;
var y:int = y0;
var ystep:int = y0<y1 ? 1 : -1;
var x:int = x0;
var xend:int = x1-(deltax>>1);
var fx:int = x1;
var fy:int = y1;
var px:int = 0;
r.x = 0;
r.y = 0;
r.width = 0;
r.height = 1;
while (x++<=xend)
{
if (steep)
{
checkLine(o,y,x,c,r);
if (fx != x1 && fx != xend)
checkLine(o,fy,fx+1,c,r);
}
error += deltay;
if ((error<<1) >= deltax)
{
if (!steep)
{
checkLine(o,x-px+1,y,c,r);
if (fx!=xend)
checkLine(o,fx+1,fy,c,r);
}
px = 0;
y += ystep;
fy -= ystep;
error -= deltax;
}
px++;
fx--;
}
if (!steep)
checkLine(o,x-px+1,y,c,r);
}
}
}
Looks like just a typo or copy/paste error. The import statement should not be repeated inside your class definition:
package views
{
import flash.display.Bitmap;
import flash.geom.Point;
import views.Canvas.Raster; // Yes
/**
* ...
* #author Arthur Wulf White
*/
public class RasterView extends Bitmap
{
import views.Canvas.Raster // No
Also, avoid having an accessor with the same name as a class:
public function get Raster():Raster // Call this function get MyRaster or similar
{
return Raster(bitmapData);
}
Code highlighting is your friend. Any time a property or function name other than your constructor lights up in Cyan, it means you're using an existing class name, which may cause problems.