482 lines
12 KiB
HTML
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>
|