@quartic/bokehjs
Version:
Interactive, novel data visualization
126 lines (100 loc) • 3.89 kB
text/coffeescript
import {Glyph, GlyphView} from "./glyph"
import {logger} from "core/logging"
import * as p from "core/properties"
export class ImageURLView extends GlyphView
initialize: (options) ->
super(options)
_index_data: () ->
_set_data: () ->
if not ? or .length != .length
= (null for img in )
retry_attempts = .retry_attempts
retry_timeout = .retry_timeout
= (retry_attempts for img in )
for i in [0....length]
if not [i]?
continue
img = new Image()
img.onerror = do (i, img) =>
return () =>
if [i] > 0
logger.trace("ImageURL failed to load #{@_url[i]} image, retrying in #{retry_timeout} ms")
setTimeout((=> img.src = [i]), retry_timeout)
else
logger.warn("ImageURL unable to load #{@_url[i]} image after #{retry_attempts} retries")
[i] -= 1
img.onload = do (img, i) =>
return () =>
[i] = img
.request_render()
img.src = [i]
_map_data: () ->
# XXX: remove this when `null` handling is improved.
ws = (if ? then else NaN for x in )
hs = (if ? then else NaN for x in )
switch .properties.w.units
when "data" then =
when "screen" then = ws
switch .properties.h.units
when "data" then =
when "screen" then = hs
_render: (ctx, indices, {_url, image, sx, sy, sw, sh, _angle}) ->
# TODO (bev): take actual border width into account when clipping
frame = .plot_view.frame
ctx.rect(
frame.left+1, frame.bottom+1,
frame.width-2, frame.height-2,
)
ctx.clip()
for i in indices
if isNaN(sx[i]+sy[i]+_angle[i])
continue
if [i] == -1
continue
if not image[i]?
continue
_final_sx_sy: (anchor, sx, sy, sw, sh) ->
switch anchor
when 'top_left' then [sx , sy ]
when 'top_center' then [sx - sw/2, sy ]
when 'top_right' then [sx - sw , sy ]
when 'center_right' then [sx - sw , sy - sh/2]
when 'bottom_right' then [sx - sw , sy - sh ]
when 'bottom_center' then [sx - sw/2, sy - sh ]
when 'bottom_left' then [sx , sy - sh ]
when 'center_left' then [sx , sy - sh/2]
when 'center' then [sx - sw/2, sy - sh/2]
_render_image: (ctx, i, image, sx, sy, sw, sh, angle) ->
if isNaN(sw[i]) then sw[i] = image.width
if isNaN(sh[i]) then sh[i] = image.height
anchor = .anchor
[sx, sy] =
ctx.save()
ctx.globalAlpha = .global_alpha
if angle[i]
ctx.translate(sx, sy)
ctx.rotate(angle[i])
ctx.drawImage(image, 0, 0, sw[i], sh[i])
ctx.rotate(-angle[i])
ctx.translate(-sx, -sy)
else
ctx.drawImage(image, sx, sy, sw[i], sh[i])
ctx.restore()
export class ImageURL extends Glyph
default_view: ImageURLView
type: 'ImageURL'
[['x', 'y']]
[]
{
url: [ p.StringSpec ]
anchor: [ p.Anchor, 'top_left' ]
global_alpha: [ p.Number, 1.0 ]
angle: [ p.AngleSpec, 0 ]
w: [ p.DistanceSpec ]
h: [ p.DistanceSpec ]
dilate: [ p.Bool, false ]
retry_attempts: [ p.Number, 0 ]
retry_timeout: [ p.Number, 0 ]
}