metanohi-misc-subsites/projects/canvas/cc.htm

482 lines
12 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Circle Class</title>
<style type='text/css'>
* {
margin: 0;
padding: 0;
position: absolute;
}
</style>
<script type='text/javascript'>
/*
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
This JS class attempts to make an interactive site with the canvas element.
In time this will not only be a cirlce class, but more like an object class.
The fun stuff happens at the end of this file.
*/
function Circle(posX, posY, radius, fillColor, borderWidth, borderColor, visible) {
// Default to defaults if nothing is specified
if (posX == undefined) var posX = 0
if (posY == undefined) var posY = 0
if (radius == undefined) var radius = 50
if (fillColor == undefined) var fillColor = '#ddd'
if (borderWidth == undefined) var borderWidth = 2
if (borderColor == undefined) var borderColor = '#444'
if (visible == undefined) var visible = true
this.visible = visible
// Get number in order of creation
this.num = objects.length
// Create canvas element
this.element = document.createElement('canvas')
if (!this.visible) this.hide()
this.element.style.zIndex = this.num + 2
wrapper.appendChild(this.element)
this.context = this.element.getContext('2d')
// Append to global objects
objects.splice(objects.length, objects.length, this)
this.state = 'normal'
this.globalstate = 'normal'
this.savedstate = 'hover'
this.x = posX
this.y = posY
this.radius = radius
this.fillColor = fillColor
this.borderWidth = borderWidth
this.borderColor = borderColor
var i
for (i in style_states) {
this[style_states[i]] = {}
this[style_states[i]].x = false
this[style_states[i]].y = false
this[style_states[i]].radius = false
this[style_states[i]].fillColor = false
this[style_states[i]].borderWidth = false
this[style_states[i]].borderColor = false
}
for (i in event_states) {
this[event_states[i]] = '' //'dbg.innerHTML+=" '+event_states[i]+'"'
}
// Keep track of mousedown events
this.mousedown_done = false
// Keep track of hovering
this.hovering = false
this.create()
}
Circle.prototype.create = function() {
var posX, posY, radius, fillColor, borderWidth, borderColor, i
posX = this.get('x')
posY = this.get('y')
radius = this.get('radius')
fillColor = this.get('fillColor')
borderWidth = this.get('borderWidth')
borderColor = this.get('borderColor')
var mn = radius * 2 + borderWidth
var mnh = mn / 2
this.element.width = mn
this.element.height = mn
this.element.style.width = mn + 'px'
this.element.style.height = mn + 'px'
this.element.style.left = posX - mnh + 'px'
this.element.style.top = posY - mnh + 'px'
// Create the circle
this.context.beginPath()
this.context.arc(mnh, mnh, radius, 0, Math.PI*2, true)
if (typeof(fillColor) == 'string')
this.context.fillStyle = fillColor
else {
if (fillColor[0] == 'linear') {
var x1, y1, x2, y2
if (fillColor.length > 2) {
var angle = (fillColor[2] + 45) % 360 // Center it
if (angle >= 0 && angle < 90) {
x1 = (angle / 90) * mn
y1 = 0
x2 = ((90 - angle) / 90) * mn
y2 = mn
}
else if (angle >= 90 && angle < 180) {
x1 = mn
y1 = ((angle - 90) / 90) * mn
x2 = 0
y2 = ((90 - (angle - 90)) / 90) * mn
}
else if (angle >= 180 && angle < 270) {
x1 = ((90 - (angle - 180)) / 90) * mn
y1 = mn
x2 = ((angle - 180) / 90) * mn
y2 = 0
}
else if (angle >= 270 && angle < 360) {
x1 = 0
y1 = ((90 - (angle - 270)) / 90) * mn
x2 = mn
y2 = ((angle - 270) / 90) * mn
}
}
else {
x1 = mnh
y1 = 0
x2 = mnh
y2 = mn
}
var grad = this.context.createLinearGradient(x1, y1, x2, y2)
}
else {
var lenpos, reallen, angle, x1, y1
if (fillColor.length > 2) {
lenpos = (fillColor[2])
if (fillColor.length > 3) {
angle = (fillColor[3] + 45)
while (angle < 0) {
angle += 360
}
angle = angle % 360
}
else angle = 0
}
else {
lenpos = 0
angle = 0
}
reallen = lenpos * radius
if (angle >= 0 && angle < 90) {
x1 = mnh + Math.sin((angle - 45) * Math.PI / 180) * reallen
y1 = mnh - Math.cos((angle - 45) * Math.PI / 180) * reallen
}
else if (angle >= 90 && angle < 180) {
x1 = mnh + Math.cos((angle - 135) * Math.PI / 180) * reallen
y1 = mnh + Math.sin((angle - 135) * Math.PI / 180) * reallen
}
else if (angle >= 180 && angle < 270) {
x1 = mnh - Math.sin((angle - 225) * Math.PI / 180) * reallen
y1 = mnh + Math.cos((angle - 225) * Math.PI / 180) * reallen
}
else if (angle >= 270 && angle < 360) {
x1 = mnh - Math.cos((angle - 315) * Math.PI / 180) * reallen
y1 = mnh - Math.sin((angle - 315) * Math.PI / 180) * reallen
}
var grad = this.context.createRadialGradient(x1, y1, 0, mnh, mnh, radius)
}
for (i in fillColor[1]) {
grad.addColorStop(i / (fillColor[1].length - 1), fillColor[1][i])
}
this.context.fillStyle = grad
}
this.context.lineWidth = borderWidth
this.context.strokeStyle = borderColor
// Clear the screen
this.context.clearRect(0, 0, mn, mn)
this.context.stroke()
this.context.fill()
}
Circle.prototype.standby = function() {
if (!this.visible) return false
var posX, posY, radius, borderWidth
posX = this.get('x')
posY = this.get('y')
radius = this.get('radius')
borderWidth = this.get('borderWidth')
if (!object_hover && Math.sqrt(Math.pow((x - posX), 2) + Math.pow((y - posY), 2)) < radius + borderWidth / 2) {
// If the cursor is inside the circle
// No more objects may react
object_hover = true
if (!this.hovering)
this.eval(this.onmouseover)
else if (x != ox || y != oy)
this.eval(this.onmousemove)
// We're hovering!
this.hovering = true
if (this.globalstate == 'onmousedown') {
this.state = 'active'
this.savedstate = 'active'
if (!this.onmousedown_done) {
this.onmousedown_done = true
this.eval(this.onmousedown)
}
}
else if (this.globalstate == 'onmouseup') {
this.state = 'hover'
this.savedstate = 'hover'
this.eval(this.onmouseup)
if (this.onmousedown_done)
this.eval(this.onclick)
this.onmousedown_done = false
}
else {
// Last resort
this.state = this.savedstate
}
}
else {
// If the cursor is outside the circle
if (this.hovering) {
// No more hovering..
this.hovering = false
this.eval(this.onmouseout)
}
// Reset everything
this.state = 'normal'
if (this.globalstate == 'onmouseup') {
this.savedstate = 'hover'
this.onmousedown_done = false
}
}
this.globalstate = 'normal'
// Create it and draw it to the screen
this.create()
return true
}
Circle.prototype.eval = function(code) {
var codetype = typeof(code)
if (codetype == 'function')
code = (code + '').split('function ')[1].split('{')[0]
try {
eval(code)
return true
}
catch(e) {
return false
}
}
Circle.prototype.getobj = function() {
if (this.state == 'normal')
return this
else
return this[this.state]
}
Circle.prototype.get = function(circlevar) {
var cobj = this.getobj()
if (cobj[circlevar] === false) {
if (this.state == 'active' && this.hover[circlevar] !== false)
return this.hover[circlevar]
else return this[circlevar]
}
else return cobj[circlevar]
}
Circle.prototype.set = function(circle_var, value) {
this[circle_var] = value
for (var i in event_states) {
this[event_states[i]][circle_var] = value
}
}
Circle.prototype.hide = function() {
this.element.style.display = 'none'
this.visible = false
}
Circle.prototype.show = function() {
this.element.style.display = 'block'
this.visible = true
}
Circle.prototype.raiseIndex = function(amount) {
if (amount == undefined) var amount = 1
return this.changeIndex(amount)
}
Circle.prototype.lowerIndex = function(amount) {
if (amount == undefined) var amount = 1
return this.changeIndex(-amount)
}
Circle.prototype.toTop = function() {
return this.changeIndex(objects.length - this.num - 1)
}
Circle.prototype.toBottom = function() {
return this.changeIndex(-this.num)
}
Circle.prototype.changeIndex = function(crement) {
if (objects.length > this.num + crement && 0 <= this.num + crement) {
objects.splice(this.num, 1)
objects.splice(this.num + crement, 0, this)
this.update_indexes()
return true
}
else
return false
}
Circle.prototype.remove = function() {
objects.splice(this.num, 1)
this.update_indexes()
wrapper.removeChild(this.element)
delete this
}
Circle.prototype.update_indexes = function() {
for (var i in objects) {
objects[i].num = i * 1
objects[i].element.style.zIndex = i * 1 + 2
}
}
function standby() {
for (var i = objects.length - 1; i > -1; i--) {
objects[i].standby()
}
object_hover = false
ox = x
oy = y
timer = setTimeout('standby()')
}
window.onload = function() {
// Globals
x = 0
y = 0
ox = 0
oy = 0
objects = new Array()
object_hover = false
getwh()
event_states = ['onmouseover', 'onmouseout', 'onmousemove', 'onmousedown', 'onmouseup', 'onclick']
style_states = ['hover', 'active']
globalstate = 'normal'
// Creating the wrapper
wrapper = document.createElement('div')
wrapper.style.position = 'absolute'
document.body.appendChild(wrapper)
/*dbg = document.createElement('div')
dbg.style.position = 'absolute'
document.body.appendChild(dbg)*/
// Adjust on resize
window.onresize = function() {
getwh()
}
window.onmousedown = function() {
for (var i in objects) {
objects[i].globalstate = 'onmousedown'
}
}
window.onmouseup = function() {
for (var i in objects) {
objects[i].globalstate = 'onmouseup'
}
}
standby()
loadobjects()
}
window.onmousemove = function(e) {
if (!e) var e = window.event
if (e.pageX || e.pageY) {
x = e.pageX
y = e.pageY
}
else if (e.clientX || e.clientY) {
x = e.clientX + document.body.scrollLeft
y = e.clientY + document.body.scrollTop
}
}
function getwh() {
if (self.innerHeight) {
h = self.innerHeight
w = self.innerWidth
}
else if (document.documentElement && document.documentElement.clientHeight) {
h = document.documentElement.clientHeight
w = document.documentElement.clientHeight
}
else if (document.body) {
h = document.body.clientHeight
w = document.body.clientWidth
}
}
function loadobjects() {
circ = new Circle(250, 250, 50, ['radial', ['#00ff00', '#dd33ee', '#888', '#00ffff']], 0, '#000')
circ.hover.fillColor = ['radial', ['#0000ff', '#dd33ee', '#333', '#00ffff']]
circ.active.fillColor = ['linear', ['#fff', '#000'], -45]
circ2 = new Circle(270, 280, 30, '#eee', 5, '#333')
circ2.hover.fillColor = '#ff00ff'
circ2.active.fillColor = '#ff0000'
circ3 = new Circle(260, 220, 25, ['radial', ['#fff', '#000']], 7, '#333')
circ3.hover.fillColor = ['radial', ['#000', '#fff']]
circ4 = new Circle(340, 290, 60, ['radial', ['rgb(221, 87, 42)', 'rgb(155, 60, 28)'], .6, -10], 0, '#333')
circ4.hover.fillColor = ['radial', ['#fff', '#000'], .4, 40]
// Below is a list of functions that can be used on a circle.
/*
changeIndex
raiseIndex
lowerIndex
toTop
toBottom
hide
show
remove
*/
}
</script>
</head>
<body></body>
</html>