initial commit

This commit is contained in:
John Bintz 2014-10-26 16:19:17 -04:00
commit 7b26ee23c9
18 changed files with 963 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/bower_components/
/node_modules/

2
.npmignore Normal file
View File

@ -0,0 +1,2 @@
dist/

46
Gruntfile.coffee Normal file
View File

@ -0,0 +1,46 @@
module.exports = (grunt) ->
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks)
grunt.initConfig {
watch:
coffee:
files: ['src/**/*.coffee']
tasks: ['browserify', 'coffee', 'uglify']
browserify:
dist:
files:
'dist/bismarck.js': 'src/bismarck.coffee'
options:
transform: ['coffeeify']
browserifyOptions:
debug: true
extensions: ['.coffee', '.litcoffee']
coffee:
lib:
expand: true
cwd: 'src'
src: ['**/*.coffee']
dest: 'lib'
ext: '.js'
options:
bare: true
karma:
unit:
configFile: 'karma.conf.js'
autoWatch: true
uglify:
options:
mangle: false
dist:
files:
'dist/bismarck.min.js': 'dist/bismarck.js'
concurrent:
default:
tasks: ['karma', 'watch']
options:
logConcurrentOutput: true
limit: 2
}
grunt.registerTask 'default', ['browserify', 'uglify', 'coffee', 'concurrent:default']

0
README.md Normal file
View File

16
bower.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "bismarck",
"version": "0.0.0",
"main": "dist/bismarck.js",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"snap.svg": "~0.3.0",
"jquery": "~2.1.1"
}
}

73
karma.conf.js Normal file
View File

@ -0,0 +1,73 @@
// Karma configuration
// Generated on Tue Sep 23 2014 07:24:39 GMT-0400 (EDT)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
preprocessors: {
'test/index.coffee': 'browserify',
'src/coffee/app.coffee': 'browserify',
},
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['browserify', 'jasmine'],
// list of files / patterns to load in the browser
files: [
'bower_components/jquery/dist/jquery.js',
'bower_components/snap.svg/dist/snap.svg.js',
'test/index.coffee'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
browserify: {
extensions: ['.coffee', '.litcoffee'],
transform: ['coffeeify'],
watch: true,
debug: true
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9877,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};

36
package.json Normal file
View File

@ -0,0 +1,36 @@
{
"name": "bismarck",
"version": "0.0.0",
"description": "",
"main": "lib/bismarck.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"browserify": "^6.1.0",
"coffeeify": "^0.7.0",
"grunt": "^0.4.5",
"grunt-browserify": "^3.1.0",
"grunt-concurrent": "^1.0.0",
"grunt-contrib-coffee": "^0.11.1",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-uglify": "^0.6.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-karma": "^0.9.0",
"karma": "^0.12.23",
"karma-bro": "^0.8.0",
"karma-chrome-launcher": "^0.1.4",
"karma-coffee-preprocessor": "^0.2.1",
"karma-firefox-launcher": "^0.1.3",
"karma-jasmine": "~0.2.2",
"karma-phantomjs-launcher": "^0.1.4",
"matchdep": "^0.3.0"
},
"dependencies": {
"q": "^1.0.1",
"underscore": "^1.7.0",
"xml2js": "^0.4.4"
}
}

15
src/bismarck.coffee Normal file
View File

@ -0,0 +1,15 @@
Canvas = require('./bismarck/canvas')
Bismarck = (element, options) ->
if typeof element == 'string'
new Canvas(document.getElementById(element), options)
else
new Canvas(element, options)
Bismarck.debug = false
module.exports = Bismarck
if window?
window.Bismarck = Bismarck

View File

@ -0,0 +1,77 @@
Animate =
_animationsEnabled: true
currentTime: -> +new Date
moveFromTo: (object, from, to, distance) ->
dx = to.x - from.x
dy = to.y - from.y
x = from.x + (dx * distance)
y = from.y + (dy * distance)
object.moveTo(x, y)
class Animate.Synchronizer
constructor: ->
@animations = []
@recalcs = []
@removers = []
@isRunning = false
@fpsLimit = 30
addAnimation: (recalc, animation) ->
@animations.push(animation)
@recalcs.push(recalc)
@removers.push => @removeAnimation(animation)
@run()
=> @removeAnimation(animation)
removeAnimation: (animation) ->
index = @animations.indexOf(animation)
@animations.splice(index, 1)
@recalcs.splice(index, 1)
@removers.splice(index, 1)
if @animations.length == 0
@isRunning = false
run: =>
if not @isRunning
@isRunning = true
window.requestAnimationFrame =>
if @animations.length > 0
startTime = Animate.currentTime()
Animate._animationsDisabled = false
for i in [0..@animations.length - 1]
if @animations[i]
@animations[i](startTime, @removers[i])
Animate._animationsDisabled = true
r.recalc() for r in @recalcs
endTime = Animate.currentTime()
if @isRunning
calc = Math.max(0, (1 / @fpsLimit - ((endTime - startTime) / 1000)) * 1000)
setTimeout(@run, calc)
else
@isRunning = false
Animate.synchronizer = new Animate.Synchronizer()
Animate.once = (recalc, options, code) ->
startTime = Animate.currentTime()
endTime = startTime + options.duration
Animate.synchronizer.addAnimation recalc, (currentTime, stop) ->
index = Math.min(1, (currentTime - startTime) / options.duration)
result = code(index)
stop() if not result or currentTime >= endTime
Animate.loop = (recalc, options, code) ->
startTime = Animate.currentTime()
Animate.synchronizer.addAnimation recalc, (currentTime, stop) ->
index = Math.min(1, (currentTime - startTime) % options.duration / options.duration)
result = code(index)
stop() if not result
module.exports = Animate

View File

@ -0,0 +1,32 @@
Drawable = require('./drawable')
Resources = require('./resources')
Layout = require('./layout')
class Canvas
constructor: (@element, options = {}) ->
@snapElement = Snap(@element)
if not @snapElement.attr('bismarck')
if options.id
@snapElement.attr(id: options.id, bismarck: 'canvas')
fromLayout: (xml, callback) ->
Layout(xml, this, callback)
create: (options) ->
drawable = new Drawable(this, options)
drawable.attachTo(@snapElement)
drawable
find: (id) ->
drawable = new Drawable(this)
drawable.useExisting(@snapElement.select("##{id}"))
drawable
resources: ->
return @_resources if @_resources
@_resources = new Resources(this)
@_resources.attachTo(@snapElement)
@_resources
module.exports = Canvas

View File

@ -0,0 +1,327 @@
Animate = require('./animate')
class Drawable
constructor: (@canvas, options = {}) ->
defaults =
centerPoint: 'northwest'
position: {x: 0, y: 0}
angle: 0
scale: 1
for own key, value of defaults
switch key
when 'centerPoint'
@setCenterPoint(value || defaults[key])
else
this[key] = value || defaults[key]
for own key, value of options
switch key
when 'centerPoint'
@setCenterPoint(value || defaults[key])
else
this[key] = value || defaults[key]
@_resources = @canvas.resources()
@_children = []
resources: -> @_resources
snapBBox: -> @_scale.getBBox(true)
create: (options) ->
drawable = new Drawable(@canvas, options)
drawable.attachTo(@_scale)
drawable.parentDrawable = this
@_children.push(drawable)
drawable
remove: ->
@_translateRotate.remove()
attachTo: (snapElement) ->
@_translateRotate = snapElement.group().addClass('-translate')
@_scale = @_translateRotate.group().addClass('-scale')
@_translateRotate.attr(id: @id, bismarck: 'drawable')
@_currentBBox = @snapBBox()
@snapElement = @_translateRotate
forceSize: (w, h) ->
@_forcedSize.remove() if @_forcedSize
@_forcedDims = { w: w, h: h }
@_forcedSize = @_translateRotate.rect(0, 0, w, h).attr(fill: 'rgba(0,0,0,0)')
me = @_forcedSize.node
@_translateRotate.node.insertBefore(me, @_translateRotate.node.childNodes[0])
useExisting: (@_translateRotate) ->
throw "Not a Bismarck element!" if not @_translateRotate.attr('bismarck')
childNodes = @_translateRotate.node.childNodes
@_scale = Snap(childNodes[0])
if childNodes[1]
@centerPointCross = Snap(childNodes[1])
currentNode = @_translateRotate.node.parentNode
while currentNode
switch currentNode.getAttribute('bismarck')
when 'drawable'
@parentDrawable = new Drawable(@canvas, {})
@parentDrawable.useExisting(Snap(currentNode))
currentNode = null
when 'canvas'
currentNode = null
else
# stop!
if currentNode.nodeName == 'svg'
currentNode = null
else
currentNode = currentNode.parentNode
angular.extend(this, @_translateRotate.data('settings'))
showCenterPoint: ->
@centerPointCross = @_translateRotate.group()
@centerPointCross.line(0, -5, 0, 5).attr(stroke: 'black')
@centerPointCross.line(-5, 0, 5, 0).attr(stroke: 'black')
@recalc()
moveTo: (x, y) ->
@position = {x: x, y: y}
@recalc()
rotateTo: (angle) ->
@angle = angle
@recalc()
scaleTo: (scale) ->
@scale = scale
@recalc()
alignTo: (object, how = 'center', args...) ->
switch how
when 'center'
@moveTo(object.position.x, object.position.y, args...)
when 'horizontal'
@moveTo(@position.x, object.position.y, args...)
when 'vertical'
@moveTo(object.position.x, @position.y, args...)
centerInParent: ->
@_centerInParent = true
@setCenterPoint('center')
@recalc(true)
recalc: (down = false) ->
if Animate._animationsEnabled
if @_centerInParent
parent = @parentDrawable.getDimensions()
@position = { x: parent.w / 2, y: parent.h / 2}
if @oldScale != @scale
matrix = new Snap.Matrix()
matrix.scale(@scale)
@_scale.transform(matrix)
@oldScale = @scale
offset = @getOffset()
upperLeft = @upperLeft()
if @centerPointCross?
matrix = new Snap.Matrix()
matrix.translate(offset.x + upperLeft.x, offset.y + upperLeft.y)
@centerPointCross.transform(matrix)
matrix = new Snap.Matrix()
matrix.translate(@position.x, @position.y)
matrix.rotate(@angle, 0, 0)
if not @_forcedSize
matrix.translate(-offset.x - upperLeft.x, -offset.y - upperLeft.y)
@_translateRotate.transform(matrix)
if false
@_translateRotate.data('settings', {
centerPoint: @centerPoint
position: @position
angle: @angle
scale: @scale
_currentBBox: @_currentBBox
_centerInParent: @_centerInParent
_forcedDims: @_forcedDims
_children: @_children
})
if down
child.recalc(true) for child in @_children
else
@parentDrawable.recalc() if @parentDrawable?
moveForward: ->
me = @_translateRotate.node
parent = me.parentNode
l = parent.childNodes.length - 1
for i in [0..l]
if parent.childNodes[i] == me and i < l
parent.insertBefore(parent.childNodes[i + 1], me)
moveBackward: ->
me = @_translateRotate.node
parent = me.parentNode
for i in [0..parent.childNodes.length]
if parent.childNodes[i] == me and i > 0
parent.insertBefore(me, parent.childNodes[i - 1])
moveToFront: ->
me = @_translateRotate.node
me.parent.appendChild(me)
moveToBack: ->
me = @_translateRotate.node
me.parent.insertBefore(me, me.parent.childNodes[0])
on: (event, args...) ->
code = args.pop()
targetSelector = args.shift()
target = @_translateRotate
if targetSelector?
target = target.select(targetSelector)
target[event](code)
draw: (code) ->
code(@_scale)
@recalc()
@_currentBBox = @snapBBox()
scaleAndRotateCoords: (coords) ->
pairs = if coords.w? then ['w', 'h'] else ['x', 'y']
coords[pairs[0]] *= @scale
coords[pairs[1]] *= @scale
rad2ang = Math.PI / 180
radianAngle = rad2ang * @angle
cos = Math.cos(radianAngle)
sin = Math.sin(radianAngle)
newW = coords[pairs[0]] * cos + coords[pairs[1]] * sin
newH = coords[pairs[1]] * cos + coords[pairs[0]] * sin
coords[pairs[0]] = newW
coords[pairs[1]] = newh
coords
getOffset: ->
output = {}
source = if @_children.length > 0
@getDimensions()
else
@_currentBBox
for coordPart in @centerPoint
output[coordPart.which] = coordPart.convert(source[coordPart.dim])
output
upperLeft: ->
if @_children.length == 0
{ x: 0, y: 0 }
else
furthestUpperLeft = { x: null, y: null }
for child in @_children
offset = child.getOffset()
offset.x = -offset.x + child.position.x
offset.y = -offset.y + child.position.y
if !furthestUpperLeft.x
furthestUpperLeft.x = offset.x
furthestUpperLeft.y = offset.y
else
furthestUpperLeft.x = Math.min(furthestUpperLeft.x, offset.x)
furthestUpperLeft.y = Math.min(furthestUpperLeft.y, offset.y)
furthestUpperLeft
setCenterPoint: (args...) ->
if args.length == 1
args = switch args[0]
when 'center'
['50%', '50%']
when 'northwest'
[0,0]
@coordinates = {}
data = [
{ index: 0, which: 'x', dim: 'w' },
{ index: 1, which: 'y', dim: 'h' }
]
coordMap = (datum) ->
datum.value = args[datum.index]
if datum.value.substr? and datum.value.substr(-1) == '%'
percent = Number(datum.value.slice(0, -1)) / 100.0
datum.convert = (value) -> value * percent
else
datum.convert = (value) -> datum.value
datum
@centerPoint = data.map(coordMap)
getDimensions: ->
if @_forcedDims
@_forcedDims
else
if @_children.length > 0
@getDimensionsWithChildren()
else
@_currentBBox
getDimensionsWithChildren: ->
bbox =
sx: null
sy: null
ex: null
ey: null
for child in @_children
childBBox = child.getDimensions()
childOffset = child.getOffset()
childBBox.x = child.position.x - childOffset.x
childBBox.y = child.position.y - childOffset.y
if bbox.sx == null
bbox.sx = childBBox.x
bbox.sy = childBBox.y
bbox.ex = childBBox.x + childBBox.w
bbox.ey = childBBox.y + childBBox.h
else
bbox.sx = Math.min(bbox.sx, childBBox.x)
bbox.sy = Math.min(bbox.sy, childBBox.y)
bbox.ex = Math.max(bbox.ex, childBBox.x + childBBox.w)
bbox.ey = Math.max(bbox.ey, childBBox.y + childBBox.h)
{ w: bbox.ex - bbox.sx, h: bbox.ey - bbox.sy }
append: (drawable) ->
@_translateRotate.append(drawable._scaleRotate)
module.exports = Drawable

View File

@ -0,0 +1,46 @@
xml2js = require('xml2js')
parseString = require('xml2js').parseString
_ = require('underscore')
svgObjs =
rect: (options, canvas) ->
rect = canvas.rect(options.x, options.y, options.width, options.height)
rect.attr(_.omit(options, 'x', 'y', 'width', 'height'))
rect
oneOrMore = (value, code) ->
if value.push?
for node in value
code(node)
else
code(value)
dive = (node, drawable, topLevel = null) ->
for own key, value of node
switch key
when 'drawable'
oneOrMore value, (v) ->
childDrawable = drawable.create(v.$)
topLevel ||= childDrawable
dive(v, childDrawable, topLevel)
when '$'
# nothing
else
oneOrMore value, (v) ->
drawable.draw (svg) ->
svgObjs[key](v.$, svg)
dive(v, drawable, topLevel)
topLevel
module.exports = (xml, canvas, callback = null) ->
parseString xml, (err, result) ->
if err?
throw err
else
diveResult = dive(result, canvas)
if callback
callback(diveResult)

View File

@ -0,0 +1,26 @@
class Resources
constructor: (@canvas) ->
@resources = {}
@bboxes = {}
attachTo: (snapElement) ->
@resourceGroup = snapElement.group().attr(display: 'none')
copyIDsFrom: (snapElement, ids...) ->
for id in ids
node = snapElement.select("##{id}")
node.transform('')
@resourceGroup.append(node)
@resources[id] = node
clone: (id) ->
@resources[id].use()
copy: (id) ->
@resources[id].clone()
bbox: (id) ->
@bboxes[id] ||= @resources[id].getBBox()
module.exports = Resources

View File

@ -0,0 +1,30 @@
Canvas = require('../../src/bismarck/canvas')
Animate = require('../../src/bismarck/animate')
describe 'Animate', ->
svg = null
canvas = null
beforeEach ->
$('body').append('<svg id="svg" width="300" height="300"></svg>')
canvas = new Canvas(document.getElementById('svg'), id: 'canvas')
afterEach ->
$('svg').remove()
describe '.moveFromTo', ->
it 'should move an object from one point to another', ->
drawable = canvas.create(id: 'drawable', centerPoint: 'northwest')
Animate.moveFromTo(drawable, {x: 0, y: 0}, {x: 100, y: 50}, 0)
expect(drawable.position).toEqual({x: 0, y: 0})
expect(drawable.snapElement.getBBox().x).toEqual(0)
Animate.moveFromTo(drawable, {x: 0, y: 0}, {x: 100, y: 50}, 0.5)
expect(drawable.position).toEqual({x: 50, y: 25})
expect(drawable.snapElement.getBBox().x).toEqual(50)
Animate.moveFromTo(drawable, {x: 0, y: 0}, {x: 100, y: 50}, 1.0)
expect(drawable.position).toEqual({x: 100, y: 50})
expect(drawable.snapElement.getBBox().x).toEqual(100)

View File

@ -0,0 +1,189 @@
Canvas = require('../../src/bismarck/canvas')
describe 'Drawable', ->
svg = null
canvas = null
drawable = null
beforeEach ->
$('body').append('<svg id="svg" width="300" height="300"></svg>')
canvas = new Canvas(document.getElementById('svg'), id: 'canvas')
drawable = canvas.create(id: 'drawable', centerPoint: 'northwest')
afterEach ->
$('svg').remove()
describe 'offset', ->
describe 'with children', ->
it 'should calculate the offset correctly', ->
childOne = drawable.create(id: 'one', centerPoint: 'northwest')
childOne.draw (surface) ->
surface.rect(0, 0, 10, 1).attr(fill: '#000000')
childTwo = drawable.create(id: 'two', centerPoint: 'northwest')
childTwo.draw (surface) ->
surface.rect(0, 0, 1, 10).attr(fill: '#000000')
expect(drawable.getOffset().x).toEqual(0)
expect(drawable.getOffset().y).toEqual(0)
drawable.setCenterPoint('50%', '50%')
expect(drawable.getOffset().x).toEqual(5)
expect(drawable.getOffset().y).toEqual(5)
childTwo.moveTo(20, 0)
expect(drawable.getOffset().x).toEqual(10.5)
expect(drawable.getOffset().y).toEqual(5)
it 'should calculate the offset correctly', ->
drawable.setCenterPoint('center')
childOne = drawable.create(id: 'one', centerPoint: 'center')
childOne.draw (surface) ->
surface.rect(0, 0, 20, 30).attr(fill: '#000000')
childOne.moveTo(0, 0)
childTwo = drawable.create(id: 'two', centerPoint: 'center')
childTwo.draw (surface) ->
surface.rect(0, 0, 20, 30).attr(fill: '#000000')
childTwo.moveTo(0, 30)
expect(drawable.getOffset().x).toEqual(10)
expect(drawable.getOffset().y).toEqual(30)
it 'should calculate the offset correctly', ->
spyOn(drawable, 'snapBBox').and.callThrough()
orect = null
drawable.setCenterPoint(0, 0)
drawable.draw (surface) ->
orect = surface.rect(0, 0, 20, 10).attr(fill: '#000000')
expect(drawable.getOffset().x).toEqual(0)
expect(drawable.getOffset().y).toEqual(0)
drawable.setCenterPoint('50%', '50%')
expect(drawable.getOffset().x).toEqual(10)
expect(drawable.getOffset().y).toEqual(5)
drawable.setCenterPoint('-100%', '0%')
expect(drawable.getOffset().x).toEqual(-20)
expect(drawable.getOffset().y).toEqual(0)
drawable.draw (surface) ->
orect = surface.rect(0, 0, 20, 10).attr(fill: 'red')
expect(drawable.getOffset().x).toEqual(-20)
expect(drawable.getOffset().y).toEqual(0)
drawable.rotateTo(90)
expect(drawable.getOffset().x).toEqual(-20)
expect(drawable.getOffset().y).toEqual(0)
drawable.setCenterPoint('center')
expect(drawable.getOffset().x).toEqual(10)
expect(drawable.getOffset().y).toEqual(5)
describe 'dimensions', ->
describe 'after drawing', ->
it 'should position the bbox correctly', ->
spyOn(drawable, 'snapBBox').and.callThrough()
orect = null
drawable.draw (surface) ->
orect = surface.rect(0, 0, 20, 10).attr(fill: '#000000')
expect(drawable.getDimensions().w).toEqual(20)
expect(drawable.getDimensions().h).toEqual(10)
drawable.draw (surface) ->
orect.remove()
surface.rect(10, 10, 20, 10).attr(fill: '#000000')
expect(drawable.getDimensions().w).toEqual(20)
expect(drawable.getDimensions().h).toEqual(10)
expect(drawable.snapBBox.calls.count()).toEqual(2)
drawable.scaleTo(2)
expect(drawable.getDimensions().w).toEqual(20)
expect(drawable.getDimensions().h).toEqual(10)
drawable.rotateTo(90)
expect(drawable.getDimensions().w).toBeCloseTo(20, 2)
expect(drawable.getDimensions().h).toBeCloseTo(10, 2)
describe 'with children', ->
describe 'northwest', ->
it 'should composite together all the drawables', ->
childOne = drawable.create(id: 'one', centerPoint: 'northwest')
childOne.draw (surface) ->
surface.rect(0, 0, 10, 1).attr(fill: '#000000')
childTwo = drawable.create(id: 'two', centerPoint: 'northwest')
childTwo.draw (surface) ->
surface.rect(0, 0, 1, 10).attr(fill: '#000000')
expect(drawable.getDimensions().w).toEqual(10)
expect(drawable.getDimensions().h).toEqual(10)
expect(drawable.upperLeft().x).toBeCloseTo(0, 1)
expect(drawable.upperLeft().y).toBeCloseTo(0, 1)
expect(childTwo.upperLeft().x).toBeCloseTo(0, 1)
expect(childTwo.upperLeft().y).toBeCloseTo(0, 1)
childTwo.moveTo(-10, 0)
expect(drawable.getDimensions().w).toEqual(20)
expect(drawable.getDimensions().h).toEqual(10)
expect(drawable.upperLeft().x).toBeCloseTo(-10, 1)
expect(drawable.upperLeft().y).toBeCloseTo(0, 1)
expect(childTwo.upperLeft().x).toBeCloseTo(0, 1)
expect(childTwo.upperLeft().y).toBeCloseTo(0, 1)
describe 'center', ->
it 'should composite together all the drawables', ->
drawable.setCenterPoint('center')
childOne = drawable.create(id: 'one', centerPoint: 'center')
childOne.draw (surface) ->
surface.rect(0, 0, 10, 20).attr(fill: '#000000')
childTwo = drawable.create(id: 'two', centerPoint: 'center')
childTwo.draw (surface) ->
surface.rect(0, 0, 10, 20).attr(fill: '#000000')
expect(drawable.getDimensions().w).toEqual(10)
expect(drawable.getDimensions().h).toEqual(20)
expect(childTwo.upperLeft().x).toBeCloseTo(0, 1)
expect(childTwo.upperLeft().y).toBeCloseTo(0, 1)
expect(drawable.upperLeft().x).toBeCloseTo(-5, 1)
expect(drawable.upperLeft().y).toBeCloseTo(-10, 1)
childTwo.rotateTo(270)
expect(drawable.getDimensions().w).toBeCloseTo(10, 2)
expect(drawable.getDimensions().h).toBeCloseTo(20, 2)

View File

@ -0,0 +1,28 @@
Canvas = require('../../src/bismarck/canvas')
describe 'layoutSpec', ->
svg = null
canvas = null
drawable = null
beforeEach ->
$('body').append('<svg id="svg" width="300" height="300"></svg>')
canvas = new Canvas(document.getElementById('svg'), id: 'canvas')
drawable = canvas.create(id: 'drawable', centerPoint: 'northwest')
svg = canvas.snapElement
afterEach ->
$('svg').remove()
describe 'from canvas', ->
it 'should create a group of objects with SVG bits', ->
layout = canvas.fromLayout("""
<drawable id="cat">
<rect id="dog" x="10" y="10" width="30" height="20" style="fill: red" />
</drawable>
""")
console.log svg.outerSVG()
expect(svg).toContainSVG('#cat')
expect(svg).toContainSVG('rect#dog[style="fill: red"]')

0
test/bismarckSpec.coffee Normal file
View File

17
test/index.coffee Normal file
View File

@ -0,0 +1,17 @@
beforeEach ->
jasmine.addMatchers {
toContainSVG: ->
compare: (svg, select) ->
result = { pass: svg.select(select)? }
result.message = if !result.pass
"Expect #{svg.outerSVG()} to contain #{select}"
result
}
require('./bismarckSpec')
require('./bismarck/animateSpec')
require('./bismarck/drawableSpec')
require('./bismarck/layoutSpec')