我正在尝试使人力车图的小部件以虚线方式更改背景颜色,具体取决于最新输入数据的最高图上的最高值。我可以在一个系列中使用它,但是我很难让它在一个图形中处理多个系列。
这是来自rickshawgraph.coffee文件的摘录。我知道我需要一个循环来获取每个序列并检查哪个序列具有最高的值,然后执行其余的逻辑,但是我在语法方面遇到了非常困难的时期。任何帮助,将不胜感激。我也包括下面的完整文件。

  node = $(@node)
  series = @_parseData {points: @get('points'), series: @get('series')}
  data = series[0].data
  values = data[data.length - 1].y
  #cool = parseInt(@get('cool'))
  cool = parseInt node.data "cool"
  #warm = parseInt(@get('warm'))
  warm = parseInt node.data "warm"
  level = switch
    when values <= cool then 0
    when values >= warm then 4
    else
      bucketSize = (warm - cool) / 3 # Total # of colours in middle
      Math.ceil (values - cool) / bucketSize

  backgroundClass = "hotness#{level}"
  lastClass = @get "lastClass"
  node.toggleClass "#{lastClass} #{backgroundClass}"

  @set "lastClass", backgroundClass


我的erb文件在这里调用小部件。
    

 

</li>


我的scss rickshawgraph.scss在这里。

// ----------------------------------------------------------------------------
// Mixins
// ----------------------------------------------------------------------------
@mixin transition($transition-property, $transition-time, $method) {
  -webkit-transition: $transition-property $transition-time $method;
  -moz-transition: $transition-property $transition-time $method;
  -o-transition: $transition-property $transition-time $method;
  transition: $transition-property $transition-time $method;
}

// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color:  #00C176;

// ----------------------------------------------------------------------------
// Widget-graph styles
// ----------------------------------------------------------------------------

.widget-rickshawgraph {
    background-color: #00C176;
    position: relative;
}
.widget-rickshawgraph .rickshaw_graph {
    position: absolute;
    left: 0px;
    top: 0px;
}
.widget-rickshawgraph svg {
    position: absolute;
    left: 0px;
    top: 0px;
}
.widget-rickshawgraph .title, .widget-rickshawgraph .value {
    position: relative;
    z-index: 99;
}
.widget-rickshawgraph .title {
    color: rgba(126, 126, 126, 0.7);
}
.widget-rickshawgraph .more-info {
    color: rgba(0, 0, 0, 0);
    font-weight: 600;
    font-size: 20px;
    margin-top: 0;
    opacity: 0;
}
.widget-rickshawgraph .x_tick {
    position: absolute;
    bottom: 0;
}
.widget-rickshawgraph .x_tick .title {
    font-size: 40px;
    color: rgba(0, 0, 0, 0.4);
    opacity: 0.5;
    padding-bottom: 3px;
}
.widget-rickshawgraph .y_ticks {
    font-size: 40px;
    fill: rgba(0, 0, 0, 0.4);
    color: rgba(0, 0, 0, 0.4);
    font-weight: bold;
}
.widget-rickshawgraph .y_ticks text {
    font-size: 20px;
    color: rgba(0, 0, 0, 0.4);
    fill: rgba(0, 0, 0, 0.4);
    font-weight: bold;
}
.widget-rickshawgraph .domain {
    display: none;
}
.widget-rickshawgraph .rickshaw_legend {
    position: absolute;
    left: 0px;
    bottom: 0px;
    white-space: nowrap;
    overflow-x: scroll;
    font-size: 80px;
    height: 20px;
}
.widget-rickshawgraph .rickshaw_legend ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
    text-align: center;
}
.widget-rickshawgraph .rickshaw_legend ul li {
    display: inline;
}
.widget-rickshawgraph .rickshaw_legend .swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-left: 5px;
}
.widget-rickshawgraph .rickshaw_legend .label {
    display: inline-block;
    margin-left: 5px;
    /*Change the font size and the text size and make sure the label comes to the front for the legend */
    font-size: 200%;
    color: rgba(255, 255, 255, 0.7);
}

.hotness0 { background-color: #00C176; }
.hotness1 { background-color: #88C100; }
.hotness2 { background-color: #FABE28; }
.hotness3 { background-color: #FF8A00; }
.hotness4 { background-color: #FF003C; }

// // More colour-blind friendly palette
// .hotness0 { background-color: #046D8B; }
// .hotness1 { background-color: #309292; }
// .hotness2 { background-color: #2FB8AC; }
// .hotness3 { background-color: #93A42A; }
// .hotness4 { background-color: #ECBE13; }


我的人力车摄影。咖啡在这里。

 # Rickshawgraphhot v0.1.0

class Dashing.Rickshawgraphhot extends Dashing.Widget

  DIVISORS = [
      {number: 100000000000000000000000,  label: 'Y'},
      {number: 100000000000000000000,     label: 'Z'},
      {number: 100000000000000000,        label: 'E'},
      {number: 1000000000000000,          label: 'P'},
      {number: 1000000000000,             label: 'T'},
      {number: 1000000000,                label: 'G'},
      {number: 1000000,                   label: 'M'},
      {number: 1000,                      label: 'S'},
      {number: 1,                         label: 'MS'}
  ]

  # Take a long number like "2356352" and turn it into "2.4M"
  formatNumber = (number) ->
      for divisior in DIVISORS
          if number > divisior.number
              number = "#{Math.round(number / (divisior.number/10))/10}#{divisior.label}"
              break
          else
           number = " number + 'ms'"

      return number

  getRenderer: () -> return @get('renderer') or @get('graphtype') or 'area'

  # Retrieve the `current` value of the graph.
  @accessor 'current', ->
    answer = null

    # Return the value supplied if there is one.
    if @get('displayedValue') != null and @get('displayedValue') != undefined
      answer = @get('displayedValue')

    if answer == null
      # Compute a value to return based on the summaryMethod
      series = @_parseData {points: @get('points'), series: @get('series')}
      if !(series?.length > 0)
        # No data in series
        answer = ''

      else
        switch @get('summaryMethod')
          when "sum"
            answer = 0
            answer += (point?.y or 0) for point in s.data for s in series

          when "sumLast"
            answer = 0
            answer += s.data[s.data.length - 1].y or 0 for s in series

          when "highest"
            answer = 0
            if @get('unstack') or (@getRenderer() is "line")
              answer = Math.max(answer, (point?.y or 0)) for point in s.data for s in series
            else
              # Compute the sum of values at each point along the graph
              for index in [0...series[0].data.length]
                value = 0
                for s in series
                  value += s.data[index]?.y or 0
                answer = Math.max(answer, value)

          when "none"
            answer = ''

          else
            # Otherwise if there's only one series, pick the most recent value from the series.
            if series.length == 1 and series[0].data?.length > 0
              data = series[0].data
              answer = data[data.length - 1].y
            else
              # Otherwise just return nothing.
              answer = ''

      if @get('numformat') == 'ms'
        answer = formatNumber answer


    return answer


  ready: ->
    @assignedColors = @get('colors').split(':') if @get('colors')
    @strokeColors = @get('strokeColors').split(':') if @get('strokeColors')

    @graph = @_createGraph()
    @graph.render()

  clear: ->
    # Remove the old graph/legend if there is one.
    $node = $(@node)
    $node.find('.rickshaw_graph').remove()
    if @$legendDiv
      @$legendDiv.remove()
      @$legendDiv = null

  # Handle new data from Dashing.
  onData: (data) ->
    series = @_parseData data

    if @graph
      # Remove the existing graph if the number of series has changed or any names have changed.
      needClear = false
      needClear |= (series.length != @graph.series.length)
      if @get("legend") then for subseries, index in series
        needClear |= @graph.series[index]?.name != series[index]?.name

      if needClear then @graph = @_createGraph()

      # Copy over the new graph data
      for subseries, index in series
        @graph.series[index] = subseries

      @graph.render()

      node = $(@node)
      series = @_parseData {points: @get('points'), series: @get('series')}
      data = series[0].data
      values = data[data.length - 1].y
      #cool = parseInt(@get('cool'))
      cool = parseInt node.data "cool"
      #warm = parseInt(@get('warm'))
      warm = parseInt node.data "warm"
      level = switch
        when values <= cool then 0
        when values >= warm then 4
        else
          bucketSize = (warm - cool) / 3 # Total # of colours in middle
          Math.ceil (values - cool) / bucketSize

      backgroundClass = "hotness#{level}"
      lastClass = @get "lastClass"
      node.toggleClass "#{lastClass} #{backgroundClass}"

      @set "lastClass", backgroundClass
  # Create a new Rickshaw graph.
  _createGraph: ->
    $node = $(@node)
    $container = $node.parent()

    @clear()

    # Gross hacks. Let's fix this.
    width = (Dashing.widget_base_dimensions[0] * $container.data("sizex")) + Dashing.widget_margins[0] * 2 * ($container.data("sizex") - 1)
    height = (Dashing.widget_base_dimensions[1] * $container.data("sizey"))

    if @get("legend")
      # Shave 20px off the bottom of the graph for the legend
      height -= 20

    $graph = $("<div style='height: #{height}px;'></div>")
    $node.append $graph
    series = @_parseData {points: @get('points'), series: @get('series')}

    graphOptions = {
      element:  $graph.get(0),
      renderer: @getRenderer(),
      width:    width,
      height:   height,
      series:   series
    }

    if !!@get('stroke') then graphOptions.stroke = true
    if @get('min') != null then graphOptions.max = @get('min')
    if @get('max') != null then graphOptions.max = @get('max')

    try
      graph = new Rickshaw.Graph graphOptions
    catch err
      if err.toString() is "x and y properties of points should be numbers instead of number and object"
        # This will happen with older versions of Rickshaw that don't support nulls in the data set.
        nullsFound = false
        for s in series
          for point in s.data
            if point.y is null
              nullsFound = true
              point.y = 0

        if nullsFound
          # Try to create the graph again now that we've patched up the data.
          graph = new Rickshaw.Graph graphOptions
          if !@rickshawVersionWarning
            console.log "#{@get 'id'} - Nulls were found in your data, but Rickshaw didn't like" +
              " them.  Consider upgrading your rickshaw to 1.4.3 or higher."
            @rickshawVersionWarning = true
        else
          # No nulls were found - this is some other problem, so just re-throw the exception.
          throw err

    graph.renderer.unstack = !!@get('unstack')

    xAxisOptions =  {
      graph: graph
    }
    if Rickshaw.Fixtures.Time.Local
      xAxisOptions.timeFixture = new Rickshaw.Fixtures.Time.Local()

    x_axis = new Rickshaw.Graph.Axis.Time xAxisOptions
    y_axis = new Rickshaw.Graph.Axis.Y(graph: graph, tickFormat: Rickshaw.Fixtures.Number.formatMS)

    if @get("legend")
      # Add a legend
      @$legendDiv = $("<div style='position:fixed; z-index:99; width: #{width}px;'></div>")
      $node.append(@$legendDiv)
      legend = new Rickshaw.Graph.Legend {
        graph: graph
        element: @$legendDiv.get(0)
      }


    return graph

  # Parse a {series, points} object with new data from Dashing.
  #
  _parseData: (data) ->
    series = []

    # Figure out what kind of data we've been passed
    if data.series
      dataSeries = if isString(data.series) then JSON.parse data.series else data.series
      for subseries, index in dataSeries
        try
          series.push @_parseSeries subseries
        catch err
          console.log "Error while parsing series: #{err}"

    else if data.points
      points = data.points
      if isString(points) then points = JSON.parse points

      if points[0]? and !points[0].x?
        # Not already in Rickshaw format; assume graphite data
        points = graphiteDataToRickshaw(points)

      series.push {data: points}

    if series.length is 0
      # No data - create a dummy series to keep Rickshaw happy
      series.push {data: [{x:0, y:0}]}

    @_updateColors(series)

    # Fix any missing data in the series.
    if Rickshaw.Series.fill then Rickshaw.Series.fill(series, null)

    return series

  # Parse a series of data from an array passed to `_parseData()`.
  # This accepts both Graphite and Rickshaw style data sets.
  _parseSeries: (series) ->
    if series?.datapoints?
      # This is a Graphite series
      answer = {
        name: series.target
        data: graphiteDataToRickshaw series.datapoints
        color: series.color
        stroke: series.stroke
      }
    else if series?.data?
      # Rickshaw data.  Need to clone, otherwise we could end up with multiple graphs sharing
      # the same data, and Rickshaw really doesn't like that.
      answer = {
        name:   series.name
        data:   series.data
        color:  series.color
        stroke: series.stroke
      }
    else if !series
      throw new Error("No data received for #{@get 'id'}")
    else
      throw new Error("Unknown data for #{@get 'id'}.  series: #{series}")

    answer.data.sort (a,b) -> a.x - b.x

    return answer

  # Update the color assignments for a series.  This will assign colors to any data that
  # doesn't have a color already.
  _updateColors: (series) ->
    # If no colors were provided, or of there aren't enough colors, then generate a set of
    # colors to use.
    if !@defaultColors or @defaultColors?.length != series.length
      @defaultColors = computeDefaultColors @, @node, series

    for subseries, index in series
      # Preferentially pick supplied colors instead of defaults, but don't overwrite a color
      # if one was supplied with the data.
      subseries.color ?= @assignedColors?[index] or @defaultColors[index]
      subseries.stroke ?= @strokeColors?[index] or "#000"

  # Convert a collection of Graphite data points into data that Rickshaw will understand.
  graphiteDataToRickshaw = (datapoints) ->
    answer = []
    for datapoint in datapoints
      # Need to convert potential nulls from Graphite into a real number for Rickshaw.
      answer.push {x: datapoint[1], y: (datapoint[0] or 0)}
    answer

  # Compute a pleasing set of default colors.  This works by starting with the background color,
  # and picking colors of intermediate luminance between the background and white (or the
  # background and black, for light colored backgrounds.)  We use the brightest color for the
  # first series, because then multiple series will appear to blend in to the background.
  computeDefaultColors = (self, node, series) ->
    defaultColors = []

    # Use a neutral color if we can't get the background-color for some reason.
    backgroundColor = parseColor($(node).css('background-color')) or [50, 50, 50, 1.0]
    hsl = rgbToHsl backgroundColor

    alpha = if self.get('defaultAlpha')? then self.get('defaultAlpha') else 1

    if self.get('colorScheme') in ['rainbow', 'near-rainbow']
      saturation = (interpolate hsl[1], 1.0, 3)[1]
      luminance = if (hsl[2] < 0.6) then 0.7 else 0.3

      hueOffset = 0
      if self.get('colorScheme') is 'rainbow'
        # Note the first and last values in `hues` will both have the same hue as the background,
        # hence the + 2.
        hues = interpolate hsl[0], hsl[0] + 1, (series.length + 2)
        hueOffset = 1
      else
        hues = interpolate hsl[0] - 0.25, hsl[0] + 0.25, series.length
      for hue, index in hues
        if hue > 1 then hues[index] -= 1
        if hue < 0 then hues[index] += 1

      for index in [0...series.length]
        defaultColors[index] = rgbToColor hslToRgb([hues[index + hueOffset], saturation, luminance, alpha])

    else
      hue = if self.get('colorScheme') is "compliment" then hsl[0] + 0.5 else hsl[0]
      if hsl[0] > 1 then hsl[0] -= 1

      saturation = hsl[1]
      saturationSource = if (saturation < 0.6) then 0.7 else 0.3
      saturations = interpolate saturationSource, saturation, (series.length + 1)

      luminance = hsl[2]
      luminanceSource = if (luminance < 0.6) then 0.9 else 0.1
      luminances = interpolate luminanceSource, luminance, (series.length + 1)

      for index in [0...series.length]
        defaultColors[index] = rgbToColor hslToRgb([hue, saturations[index], luminances[index], alpha])

    return defaultColors



# Helper functions
# ================
isString = (obj) ->
  return toString.call(obj) is "[object String]"

# Parse a `rgb(x,y,z)` or `rgba(x,y,z,a)` string.
parseRgbaColor = (colorString) ->
  match = /^rgb\(\s*([\d]+)\s*,\s*([\d]+)\s*,\s*([\d]+)\s*\)/.exec(colorString)
  if match
    return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3]), 1.0]

  match = /^rgba\(\s*([\d]+)\s*,\s*([\d]+)\s*,\s*([\d]+)\s*,\s*([\d]+)\s*\)/.exec(colorString)
  if match
    return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3]), parseInt(match[4])]

  return null

# Parse a color string as RGBA
parseColor = (colorString) ->
  answer = null

  # Try to use the browser to parse the color for us.
  div = document.createElement('div')
  div.style.color = colorString
  if div.style.color
    answer = parseRgbaColor div.style.color

  if !answer
    match = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})/.exec(colorString)
    if match then answer = [parseInt(match[1], 16), parseInt(match[2], 16), parseInt(match[3], 16), 1.0]

  if !answer
    match = /^#([\da-fA-F])([\da-fA-F])([\da-fA-F])/.exec(colorString)
    if match then answer = [parseInt(match[1], 16) * 0x11, parseInt(match[2], 16) * 0x11, parseInt(match[3], 16) * 0x11, 1.0]

  if !answer then answer = parseRgbaColor colorString

  return answer

# Convert an RGB or RGBA color to a CSS color.
rgbToColor = (rgb) ->
  if (!3 of rgb) or (rgb[3] == 1.0)
    return "rgb(#{rgb[0]},#{rgb[1]},#{rgb[2]})"
  else
    return "rgba(#{rgb[0]},#{rgb[1]},#{rgb[2]},#{rgb[3]})"

# Returns an array of size `steps`, where the first value is `source`, the last value is `dest`,
# and the intervening values are interpolated.  If steps < 2, then returns `[dest]`.
#
interpolate = (source, dest, steps) ->
  if steps < 2
    answer =[dest]
  else
    stepSize = (dest - source) / (steps - 1)
    answer = (num for num in [source..dest] by stepSize)
    # Rounding errors can cause us to drop the last value
    if answer.length < steps then answer.push dest

  return answer

# Adapted from http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
#
# Converts an RGBA color value to HSLA. Conversion formula
# adapted from http://en.wikipedia.org/wiki/HSL_color_space.
# Assumes r, g, and b are contained in the set [0, 255] and
# a in [0, 1].  Returns h, s, l, a in the set [0, 1].
#
# Returns the HSLA representation as an array.
rgbToHsl = (rgba) ->
  [r,g,b,a] = rgba
  r /= 255
  g /= 255
  b /= 255
  max = Math.max(r, g, b)
  min = Math.min(r, g, b)
  l = (max + min) / 2

  if max == min
    h = s = 0 # achromatic
  else
    d = max - min
    s = if l > 0.5 then d / (2 - max - min) else d / (max + min)
    switch max
      when r then h = (g - b) / d + (g < b ? 6 : 0)
      when g then h = (b - r) / d + 2
      when b then h = (r - g) / d + 4
    h /= 6;

  return [h, s, l, a]

# Adapted from http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
#
# Converts an HSLA color value to RGBA. Conversion formula
# adapted from http://en.wikipedia.org/wiki/HSL_color_space.
# Assumes h, s, l, and a are contained in the set [0, 1] and
# returns r, g, and b in the set [0, 255] and a in [0, 1].
#
# Retunrs the RGBA representation as an array.
hslToRgb = (hsla) ->
  [h,s,l,a] = hsla
  if s is 0
    r = g = b = l # achromatic
  else
    hue2rgb = (p, q, t) ->
      if(t < 0)   then t += 1
      if(t > 1)   then t -= 1
      if(t < 1/6) then return p + (q - p) * 6 * t
      if(t < 1/2) then return q
      if(t < 2/3) then return p + (q - p) * (2/3 - t) * 6
      return p

    q = if l < 0.5 then l * (1 + s) else l + s - l * s
    p = 2 * l - q;
    r = hue2rgb(p, q, h + 1/3)
    g = hue2rgb(p, q, h)
    b = hue2rgb(p, q, h - 1/3)

  return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a]


我的rickshawgraph.html在这里。

<h1 class="title" data-bind="title" style="color:white;"> </h1>
<h2 class="value" data-bind="current | prepend prefix"></h2>
<p class="more-info" data-bind="moreinfo"></p>

最佳答案

我建议您改为这样做。在“资产/样式表/application.scss”中设置了警告和危险颜色。您可以在其中添加新颜色。

在您的人力车图小部件中添加此

onData: (data) ->
 if data.status
    # clear existing "status-*" classes
    $(@get('node')).attr 'class', (i,c) ->
      c.replace /\bstatus-\S+/g, ''
    # add new class
    $(@get('node')).addClass "status-#{data.status}"


在工作的.rb中,设置一个状态并发送。

例如:

if count < 50
   status = 'warning'
else
   status = 'danger'
end

send_event('thread-count', { value: count, status: status } )


在上述情况下,如果我的计数小于50,则闪烁黄色,否则闪烁红色。

注意:该动画在Firefox中不起作用。仅适用于Safari和Chrome。

09-07 11:38