Search code examples
javascriptruby-on-railscoffeescriptsnap.svg

Cannot get Snap.svg to select the proper svg element in Rails


I'm trying to get Snap.svg to work in my Rails project.

I have a page foo.html.slim containing the following code:

#svg-container
  svg#apple height="1000" width="400"

And in static_pages.js.coffee, I have

svgElement = document.getElementById("apple")
paper = Snap(svgElement)
circ = paper.circle(100, 100, 50)
circ.attr
  fill: "#ff0000"
  stroke: "#0000ff"
  strokeWidth: 10
circ.drag()

This doesn't render the SVG anywhere on the page (the element isn't in the html source anywhere); however, if I add a line in a particular place like so

svgElement = document.getElementById("apple")
document.write("foo") # this is the new line
paper = Snap(svgElement)
circ = paper.circle(100, 100, 50)
circ.attr
  fill: "#ff0000"
  stroke: "#0000ff"
  strokeWidth: 10
circ.drag()

A red and blue circle gets drawn. The problem is it is at the very top of the body of the html rather than in the svg element that it should have selected. Also of note, if the document.write("foo") line is placed in a different position in the coffeescript file, the circle doesn't get drawn.

Neither also does paper = Snap("#apple") work instead of the original code.

What is the proper way to have the svg circle drawn in the existing svg element?


Solution

  • Sounds like you're trying to access #apple before it is there. The easiest solution is wrap the code that needs #apple in a document-ready handler, in CoffeeScript that would look like this:

    $ ->
      svgElement = document.getElementById("apple")
      paper = Snap(svgElement)
      circ = paper.circle(100, 100, 50)
      circ.attr
        fill: "#ff0000"
        stroke: "#0000ff"
        strokeWidth: 10
      circ.drag()
    

    That's the same as $(function() { ... }) in JavaScript.