JS: update webdemo canvas examples

This commit is contained in:
Sergey Mashkov
2015-10-28 12:52:07 +03:00
parent 3b68aaa84c
commit 20aff28266
4 changed files with 115 additions and 119 deletions
@@ -6,12 +6,8 @@ package creatures
import java.util.ArrayList
import jquery.*
import kotlin.js.dom.html.window
import kotlin.js.dom.html.HTMLElement
import kotlin.js.dom.html.HTMLImageElement
import kotlin.js.dom.html5.CanvasContext
import kotlin.js.dom.html5.CanvasGradient
import kotlin.js.dom.html5.HTMLCanvasElement
import kotlin.browser.window
import org.w3c.dom.*
fun getImage(path: String): HTMLImageElement {
@@ -25,22 +21,22 @@ val canvas: HTMLCanvasElement
return window.document.getElementsByTagName("canvas").item(0)!! as HTMLCanvasElement
}
val context: CanvasContext
val context: CanvasRenderingContext2D
get() {
return canvas.getContext("2d")!!
return canvas.getContext("2d") as CanvasRenderingContext2D
}
abstract class Shape() {
abstract fun draw(state: CanvasState)
// these two abstract methods defines that our shapes can be dragged
abstract fun contains(mousePos: Vector): Boolean
abstract operator fun contains(mousePos: Vector): Boolean
abstract var pos: Vector
var selected: Boolean = false
// a couple of helper extension methods we'll be using in the derived classes
fun CanvasContext.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasContext.() -> Unit) {
fun CanvasRenderingContext2D.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasRenderingContext2D.() -> Unit) {
save()
shadowColor = "rgba(100, 100, 100, $alpha)"
shadowBlur = 5.0
@@ -50,7 +46,7 @@ abstract class Shape() {
restore()
}
fun CanvasContext.fillPath(constructPath: CanvasContext.() -> Unit) {
fun CanvasRenderingContext2D.fillPath(constructPath: CanvasRenderingContext2D.() -> Unit) {
beginPath()
constructPath()
closePath()
@@ -73,10 +69,10 @@ class Logo(override var pos: Vector) : Shape() {
fun drawLogo(state: CanvasState) {
size = imageSize * (state.size.x / imageSize.x) * relSize
// getKotlinLogo() is a 'magic' function here defined only for purposes of demonstration but in fact it just find an element containing the logo
state.context.drawImage(getImage("http://kotlin-demo.jetbrains.com/static/images/kotlinlogowobackground.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
position.x.toInt(), position.y.toInt(),
size.x.toInt(), size.y.toInt())
state.context.drawImage(getImage("http://kotlin-demo.jetbrains.com/static/images/kotlinlogowobackground.png"), 0.0, 0.0,
imageSize.x, imageSize.y,
position.x, position.y,
size.x, size.y)
}
override fun draw(state: CanvasState) {
@@ -123,12 +119,12 @@ class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
override fun contains(mousePos: Vector) = pos distanceTo mousePos < radius
// defining more nice extension functions
fun CanvasContext.circlePath(position: Vector, rad: Double) {
fun CanvasRenderingContext2D.circlePath(position: Vector, rad: Double) {
arc(position.x, position.y, rad, 0.0, 2 * Math.PI, false)
}
//notice we can use an extension function we just defined inside another extension function
fun CanvasContext.fillCircle(position: Vector, rad: Double) {
fun CanvasRenderingContext2D.fillCircle(position: Vector, rad: Double) {
fillPath {
circlePath(position, rad)
}
@@ -144,7 +140,7 @@ class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
}
}
fun drawCreature(context: CanvasContext) {
fun drawCreature(context: CanvasRenderingContext2D) {
context.fillStyle = getGradient(context)
context.fillPath {
tailPath(context)
@@ -153,16 +149,16 @@ class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
drawEye(context)
}
fun getGradient(context: CanvasContext): CanvasGradient {
fun getGradient(context: CanvasRenderingContext2D): CanvasGradient {
val gradientCentre = position + directionToLogo * (radius / 4)
val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius)!!
val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius)
for (colorStop in colorStops) {
gradient.addColorStop(colorStop.first, colorStop.second)
}
return gradient
}
fun tailPath(context: CanvasContext) {
fun tailPath(context: CanvasRenderingContext2D) {
val tailDirection = -directionToLogo
val tailPos = position + tailDirection * radius * 1.0
val tailSize = radius * 1.6
@@ -170,13 +166,13 @@ class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
val p1 = tailPos + tailDirection.rotatedBy(angle) * tailSize
val p2 = tailPos + tailDirection.rotatedBy(-angle) * tailSize
val middlePoint = position + tailDirection * radius * 1.0
context.moveTo(tailPos.x.toInt(), tailPos.y.toInt())
context.lineTo(p1.x.toInt(), p1.y.toInt())
context.moveTo(tailPos.x, tailPos.y)
context.lineTo(p1.x, p1.y)
context.quadraticCurveTo(middlePoint.x, middlePoint.y, p2.x, p2.y)
context.lineTo(tailPos.x.toInt(), tailPos.y.toInt())
context.lineTo(tailPos.x, tailPos.y)
}
fun drawEye(context: CanvasContext) {
fun drawEye(context: CanvasRenderingContext2D) {
val eyePos = directionToLogo * radius * 0.6 + position
val eyeRadius = radius / 3
val eyeLidRadius = eyeRadius / 2
@@ -186,7 +182,7 @@ class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
context.fillCircle(eyePos, eyeLidRadius)
}
fun drawCreatureWithShadow(context: CanvasContext) {
fun drawCreatureWithShadow(context: CanvasRenderingContext2D) {
context.shadowed(shadowOffset, 0.7) {
context.fillStyle = getGradient(context)
fillPath {
@@ -199,8 +195,8 @@ class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
}
class CanvasState(val canvas: HTMLCanvasElement) {
var width = canvas.width
var height = canvas.height
var width = canvas.width.toDouble()
var height = canvas.height.toDouble()
val size: Vector
get() = v(width, height)
val context = creatures.context
@@ -255,9 +251,9 @@ class CanvasState(val canvas: HTMLCanvasElement) {
var offset = Vector()
var element: HTMLElement? = canvas
while (element != null) {
val el: HTMLElement = element!!
val el: HTMLElement = element
offset += Vector(el.offsetLeft, el.offsetTop)
element = el.offsetParent
element = el.offsetParent as HTMLElement?
}
return Vector(e.pageX, e.pageY) - offset
}
@@ -269,10 +265,10 @@ class CanvasState(val canvas: HTMLCanvasElement) {
fun clear() {
context.fillStyle = "#FFFFFF"
context.fillRect(0, 0, width.toInt(), height.toInt())
context.fillRect(0.0, 0.0, width, height)
context.strokeStyle = "#000000"
context.lineWidth = 4.0
context.strokeRect(0, 0, width.toInt(), height.toInt())
context.strokeRect(0.0, 0.0, width, height)
}
fun draw() {
@@ -287,7 +283,7 @@ class CanvasState(val canvas: HTMLCanvasElement) {
}
}
class RadialGradientGenerator(val context: CanvasContext) {
class RadialGradientGenerator(val context: CanvasRenderingContext2D) {
val gradients = ArrayList<Array<out Pair<Double, String>>>()
var current = 0
@@ -306,7 +302,7 @@ class RadialGradientGenerator(val context: CanvasContext) {
fun getNext(): Array<out Pair<Double, String>> {
val result = gradients.get(current)
current = (current + 1) % gradients.size()
current = (current + 1) % gradients.size
return result
}
}
@@ -314,11 +310,11 @@ class RadialGradientGenerator(val context: CanvasContext) {
fun v(x: Double, y: Double) = Vector(x, y)
class Vector(val x: Double = 0.0, val y: Double = 0.0) {
fun plus(v: Vector) = v(x + v.x, y + v.y)
fun minus() = v(-x, -y)
fun minus(v: Vector) = v(x - v.x, y - v.y)
fun times(koef: Double) = v(x * koef, y * koef)
fun distanceTo(v: Vector) = Math.sqrt((this - v).sqr)
operator fun plus(v: Vector) = v(x + v.x, y + v.y)
operator fun unaryMinus() = v(-x, -y)
operator fun minus(v: Vector) = v(x - v.x, y - v.y)
operator fun times(koef: Double) = v(x * koef, y * koef)
infix fun distanceTo(v: Vector) = Math.sqrt((this - v).sqr)
fun rotatedBy(theta: Double): Vector {
val sin = Math.sin(theta)
val cos = Math.cos(theta)
@@ -326,7 +322,7 @@ class Vector(val x: Double = 0.0, val y: Double = 0.0) {
}
fun isInRect(topLeft: Vector, size: Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
(y >= topLeft.y) && (y <= topLeft.y + size.y)
(y >= topLeft.y) && (y <= topLeft.y + size.y)
val sqr: Double
get() = x * x + y * y
@@ -342,13 +338,14 @@ fun main(args: Array<String>) {
state.addShape(Creature(state.size * 0.75, state))
window.setTimeout({
state.valid = false
Unit
}, 1000)
}
}
fun <T> List<T>.reversed(): List<T> {
val result = ArrayList<T>()
var i = size()
var i = size
while (i > 0) {
result.add(get(--i))
}
@@ -6,8 +6,8 @@ Note that only a subset of the api is supported for now.
package fancylines
import kotlin.js.dom.html.window
import kotlin.js.dom.html5.*
import kotlin.browser.window
import org.w3c.dom.*
import jquery.*
fun main(args: Array<String>) {
@@ -22,9 +22,9 @@ val canvas: HTMLCanvasElement
}
class FancyLines() {
val context = canvas.getContext("2d")!!
val height = canvas.height
val width = canvas.width
val context = canvas.getContext("2d") as CanvasRenderingContext2D
val height = canvas.height.toDouble()
val width = canvas.width.toDouble()
var x = width * Math.random()
var y = height * Math.random()
var hue = 0;
@@ -35,7 +35,7 @@ class FancyLines() {
context.beginPath();
context.lineWidth = 20.0 * Math.random();
context.moveTo(x.toInt(), y.toInt());
context.moveTo(x, y);
x = width * Math.random();
y = height * Math.random();
@@ -57,7 +57,7 @@ class FancyLines() {
fun blank() {
context.fillStyle = "rgba(255,255,1,0.1)";
context.fillRect(0, 0, width, height);
context.fillRect(0.0, 0.0, width, height);
}
fun run() {
@@ -3,8 +3,8 @@
*/
package hello
import kotlin.js.dom.html.window
import kotlin.js.dom.html5.*
import kotlin.browser.window
import org.w3c.dom.*
import jquery.*
val canvas: HTMLCanvasElement
@@ -12,20 +12,20 @@ val canvas: HTMLCanvasElement
return window.document.getElementsByTagName("canvas").item(0)!! as HTMLCanvasElement
}
val context: CanvasContext
val context: CanvasRenderingContext2D
get() {
return canvas.getContext("2d")!!
return canvas.getContext("2d") as CanvasRenderingContext2D
}
val width: Double
get() {
return canvas.width
return canvas.width.toDouble()
}
val height: Double
get() {
return canvas.height
return canvas.height.toDouble()
}
@@ -48,7 +48,7 @@ class HelloKotlin() {
init {
context.font = "bold ${textHeightInPixels}px Georgia, serif"
}
val textWidthInPixels = context.measureText(message)!!.width
val textWidthInPixels = context.measureText(message).width
fun draw() {
context.save()
@@ -59,7 +59,7 @@ class HelloKotlin() {
context.shadowOffsetX = -4.0
context.shadowOffsetY = 4.0
context.fillStyle = "rgb(242,160,110)"
context.fillText(message, absX.toInt(), absY.toInt())
context.fillText(message, absX, absY)
context.restore()
}
@@ -86,7 +86,7 @@ class HelloKotlin() {
fun renderBackground() {
context.save()
context.fillStyle = "#5C7EED"
context.fillRect(0, 0, width, height)
context.fillRect(0.0, 0.0, width, height)
context.restore()
}
@@ -106,5 +106,3 @@ fun main(args: Array<String>) {
}, interval)
}
}
@@ -1,11 +1,8 @@
package traffic
import java.util.ArrayList
import kotlin.js.dom.html5.CanvasContext
import kotlin.js.dom.html5.HTMLCanvasElement
import kotlin.js.dom.html.HTMLImageElement
import kotlin.js.dom.html.window
import kotlin.js.dom.html.HTMLElement
import kotlin.browser.window
import org.w3c.dom.*
import jquery.*
fun getImage(path: String): HTMLImageElement {
@@ -19,9 +16,9 @@ val canvas: HTMLCanvasElement
return window.document.getElementsByTagName("canvas").item(0)!! as HTMLCanvasElement
}
val context: CanvasContext
val context: CanvasRenderingContext2D
get() {
return canvas.getContext("2d")!!
return canvas.getContext("2d") as CanvasRenderingContext2D
}
@@ -69,10 +66,10 @@ fun v(x: Double, y: Double) = Vector(x, y)
class Image(val src: String, override var pos: Vector, var imageSize: Vector) : Shape() {
override fun draw() {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
state.context.drawImage(getImage(src), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
imageSize.x, imageSize.y)
}
fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, imageSize)
@@ -85,25 +82,25 @@ class Button(val src: String, override var pos: Vector, var imageSize: Vector) :
override fun draw() {
if (isMouseOver) {
state.context.shadowed(v(-3.0, 3.0), 1.2) {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
state.context.drawImage(getImage(src), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
imageSize.x, imageSize.y)
}
}
else if (isMouseDown) {
state.context.shadowed(v(-3.0, 3.0), 0.8) {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
state.context.drawImage(getImage(src), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
imageSize.x, imageSize.y)
}
}
else {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
state.context.drawImage(getImage(src), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
imageSize.x, imageSize.y)
}
}
@@ -111,6 +108,7 @@ class Button(val src: String, override var pos: Vector, var imageSize: Vector) :
isMouseDown = true
window.setTimeout({
isMouseDown = false
Unit
}, 1000)
}
@@ -118,6 +116,7 @@ class Button(val src: String, override var pos: Vector, var imageSize: Vector) :
isMouseOver = true
window.setTimeout({
isMouseOver = false
Unit
}, 1000)
}
@@ -130,13 +129,13 @@ class Border() : Shape() {
override fun draw() {
state.context.fillStyle = colors.white
state.context.fillRect(2, 4, 10, 292)
state.context.fillRect(330, 4, 370, 292)
state.context.fillRect(2, 2, 330, 10)
state.context.fillRect(4, 265, 340, 380)
state.context.fillRect(2.0, 4.0, 10.0, 292.0)
state.context.fillRect(330.0, 4.0, 370.0, 292.0)
state.context.fillRect(2.0, 2.0, 330.0, 10.0)
state.context.fillRect(4.0, 265.0, 340.0, 380.0)
state.context.strokeStyle = colors.black
state.context.lineWidth = 4.0
state.context.strokeRect(0, 0, state.width.toInt(), state.height.toInt())
state.context.strokeRect(0.0, 0.0, state.width, state.height)
}
}
@@ -150,7 +149,7 @@ class Timer(override var pos: Vector) : Shape() {
timeLeftForChangeColor = ("" + (timerLength - (Date().getTime() - timeStartLastChangeColor) / 1000)).get(0)
state.context.font = "bold 9px Arial, serif"
state.context.fillStyle = colors.black
state.context.fillText("" + timeLeftForChangeColor, pos.x.toInt(), pos.y.toInt())
state.context.fillText("" + timeLeftForChangeColor, pos.x, pos.y)
}
fun resetTimer() {
@@ -220,6 +219,7 @@ class TrafficLight(override var pos: Vector, val direction: String, val startCol
window.setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false
currentColor = "green"
Unit
}, 3000)
}
@@ -232,6 +232,7 @@ class TrafficLight(override var pos: Vector, val direction: String, val startCol
window.setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false
currentColor = "red"
Unit
}, 1000)
}, 2000)
}
@@ -265,10 +266,10 @@ class TrafficLightItem(override var pos: Vector, val imageSrc: String) : Shape()
}
}
else {
state.context.drawImage(getImage(PATH_TO_IMAGES + "green_color.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt())
state.context.drawImage(getImage(PATH_TO_IMAGES + "green_color.png"), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
size.x, size.y)
if (countOfFlash > 6) {
isFlashNow = true
countOfFlash = 0
@@ -279,10 +280,10 @@ class TrafficLightItem(override var pos: Vector, val imageSrc: String) : Shape()
}
}
else {
state.context.drawImage(getImage(imageSrc), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt())
state.context.drawImage(getImage(imageSrc), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
size.x, size.y)
}
}
}
@@ -294,10 +295,10 @@ class Car(override var pos: Vector, val direction: String, val color: String) :
override fun draw() {
if (direction == "up" || direction == "down") {
state.context.drawImage(getImage(PATH_TO_IMAGES + color + "_car.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
state.context.drawImage(getImage(PATH_TO_IMAGES + color + "_car.png"), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
imageSize.x, imageSize.y)
if ((!isNearStopLine()) || (trafficLightUp.canMove() && isNearStopLine()) ) {
move()
}
@@ -306,10 +307,10 @@ class Car(override var pos: Vector, val direction: String, val color: String) :
}
}
else {
state.context.drawImage(getImage(PATH_TO_IMAGES + color + "_car.png"), 0, 0,
imageSize.y.toInt(), imageSize.x.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.y.toInt(), imageSize.x.toInt())
state.context.drawImage(getImage(PATH_TO_IMAGES + color + "_car.png"), 0.0, 0.0,
imageSize.y, imageSize.x,
pos.x, pos.y,
imageSize.y, imageSize.x)
if ((!isNearStopLine()) || (trafficLightLeft.canMove() && isNearStopLine()) ) {
move()
}
@@ -356,10 +357,10 @@ class Map(override var pos: Vector) : Shape() {
override fun draw() {
size = imageSize * relSize
state.context.drawImage(getImage(PATH_TO_IMAGES + "crossroads.jpg"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt())
state.context.drawImage(getImage(PATH_TO_IMAGES + "crossroads.jpg"), 0.0, 0.0,
imageSize.x, imageSize.y,
pos.x, pos.y,
size.x, size.y)
}
}
@@ -368,8 +369,8 @@ class CanvasState(val canvas: HTMLCanvasElement) {
val context = traffic.context
var shapes = ArrayList<Shape>()
var width = canvas.width
var height = canvas.height
var width = canvas.width.toDouble()
var height = canvas.height.toDouble()
val size: Vector
get() = v(width, height)
@@ -437,9 +438,9 @@ class CanvasState(val canvas: HTMLCanvasElement) {
var offset = Vector()
var element: HTMLElement? = canvas
while (element != null) {
val el: HTMLElement = element!!
val el: HTMLElement = element
offset += Vector(el.offsetLeft, el.offsetTop)
element = el.offsetParent
element = el.offsetParent as HTMLElement?
}
return Vector(e.pageX, e.pageY) - offset
}
@@ -453,7 +454,7 @@ class CanvasState(val canvas: HTMLCanvasElement) {
fun clear() {
context.fillStyle = colors.white
context.fillRect(0, 0, width.toInt(), height.toInt())
context.fillRect(0.0, 0.0, width, height)
}
}
@@ -462,7 +463,7 @@ abstract class Shape() {
abstract fun draw()
// a couple of helper extension methods we'll be using in the derived classes
fun CanvasContext.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasContext.() -> Unit) {
fun CanvasRenderingContext2D.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasRenderingContext2D.() -> Unit) {
save()
shadowColor = "rgba(100, 100, 100, $alpha)"
shadowBlur = 5.0
@@ -472,7 +473,7 @@ abstract class Shape() {
restore()
}
fun CanvasContext.fillPath(constructPath: CanvasContext.() -> Unit) {
fun CanvasRenderingContext2D.fillPath(constructPath: CanvasRenderingContext2D.() -> Unit) {
beginPath()
constructPath()
closePath()
@@ -482,9 +483,9 @@ abstract class Shape() {
}
class Vector(val x: Double = 0.0, val y: Double = 0.0) {
fun plus(v: Vector) = v(x + v.x, y + v.y)
fun minus() = v(-x, -y)
fun minus(v: Vector) = v(x - v.x, y - v.y)
operator fun plus(v: Vector) = v(x + v.x, y + v.y)
operator fun minus() = v(-x, -y)
operator fun minus(v: Vector) = v(x - v.x, y - v.y)
fun times(koef: Double) = v(x * koef, y * koef)
fun distanceTo(v: Vector) = Math.sqrt((this - v).sqr)
fun rotatedBy(theta: Double): Vector {
@@ -494,7 +495,7 @@ class Vector(val x: Double = 0.0, val y: Double = 0.0) {
}
fun isInRect(topLeft: Vector, size: Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
(y >= topLeft.y) && (y <= topLeft.y + size.y)
(y >= topLeft.y) && (y <= topLeft.y + size.y)
val sqr: Double
get() = x * x + y * y