11# https://plot.ly/javascript/getting-started
22
33_plotly_framestyle(style:: Symbol ) =
4- if style in (:box, :axes, :zerolines, :grid, :none)
5- style
6- else
7- default_style = get((semi = :box, origin = :zerolines), style, :axes)
8- @warn " Framestyle :$style is not supported by Plotly and PlotlyJS. :$default_style was chosen instead."
9- default_style
10- end
4+ if style in (:box, :axes, :zerolines, :grid, :none)
5+ style
6+ else
7+ default_style = get((semi = :box, origin = :zerolines), style, :axes)
8+ @warn " Framestyle :$style is not supported by Plotly and PlotlyJS. :$default_style was chosen instead."
9+ default_style
10+ end
1111
1212# --------------------------------------------------------------------------------------
1313
@@ -289,13 +289,11 @@ function plotly_layout(plt::Plot)
289289 for ann in sp[:annotations]
290290 append!(
291291 plotattributes_out[:annotations],
292- KW[
293- plotly_annotation_dict(
294- locate_annotation(sp, ann... ). .. ;
295- xref = " x$(x_idx) " ,
296- yref = " y$(y_idx) " ,
297- ),
298- ],
292+ KW[plotly_annotation_dict(
293+ locate_annotation(sp, ann... ). .. ;
294+ xref = " x$(x_idx) " ,
295+ yref = " y$(y_idx) " ,
296+ ),],
299297 )
300298 end
301299 # series_annotations
@@ -335,7 +333,8 @@ function plotly_layout(plt::Plot)
335333 plotattributes_out[:hovermode] = " none"
336334 end
337335
338- return plotattributes_out = recursive_merge(plotattributes_out, plt. attr[:extra_plot_kwargs])
336+ return plotattributes_out =
337+ recursive_merge(plotattributes_out, plt. attr[:extra_plot_kwargs])
339338end
340339
341340function plotly_add_legend!(plotattributes_out:: KW , sp:: Subplot )
@@ -404,12 +403,12 @@ end
404403plotly_legend_pos(pos:: Symbol ) =
405404 get(plotly_legend_position_mapping, pos, plotly_legend_position_mapping. default)
406405
407- plotly_legend_pos(v:: Tuple{S, T} ) where {S <: Real , T <: Real } =
406+ plotly_legend_pos(v:: Tuple{S,T} ) where {S<: Real ,T <: Real } =
408407 (coords = v, xanchor = " left" , yanchor = " top" )
409408
410409plotly_legend_pos(theta:: Real ) = plotly_legend_pos((theta, :inner))
411410
412- function plotly_legend_pos(v:: Tuple{S, Symbol} ) where {S <: Real }
411+ function plotly_legend_pos(v:: Tuple{S,Symbol} ) where {S<: Real }
413412 (s, c) = sincosd(v[1 ])
414413 xanchors = [" left" , " center" , " right" ]
415414 yanchors = [" bottom" , " middle" , " top" ]
@@ -435,12 +434,12 @@ plotly_layout_json(plt::Plot) = JSON.json(plotly_layout(plt), 4)
435434plotly_colorscale(cg:: ColorGradient , α = nothing ) =
436435 map(v -> [v, rgba_string(plot_color(cg. colors[v], α))], cg. values)
437436plotly_colorscale(c:: AbstractVector{<:Colorant} , α = nothing ) =
438- if length(c) == 1
439- [[0.0 , rgba_string(plot_color(c[1 ], α))], [1.0 , rgba_string(plot_color(c[1 ], α))]]
440- else
441- vals = range(0.0 , stop = 1.0 , length = length(c))
442- map(i -> [vals[i], rgba_string(plot_color(c[i], α))], eachindex(c))
443- end
437+ if length(c) == 1
438+ [[0.0 , rgba_string(plot_color(c[1 ], α))], [1.0 , rgba_string(plot_color(c[1 ], α))]]
439+ else
440+ vals = range(0.0 , stop = 1.0 , length = length(c))
441+ map(i -> [vals[i], rgba_string(plot_color(c[i], α))], eachindex(c))
442+ end
444443
445444function plotly_colorscale(cg:: PlotUtils.CategoricalColorGradient , α = nothing )
446445 n = length(cg)
@@ -508,33 +507,33 @@ end
508507plotly_data(v) = v != = nothing ? collect(v) : v
509508plotly_data(v:: AbstractArray ) = v
510509plotly_data(surf:: Surface ) = surf. surf
511- plotly_data(v:: AbstractArray{R} ) where {R <: Rational } = float(v)
510+ plotly_data(v:: AbstractArray{R} ) where {R<: Rational } = float(v)
512511
513512plotly_native_data(axis:: Axis , a:: Surface ) = Surface(plotly_native_data(axis, a. surf))
514513plotly_native_data(axis:: Axis , data:: AbstractArray ) =
515- if ! isempty(axis[:discrete_values])
516- map(
517- xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)],
518- data,
519- )
520- elseif axis[:formatter] in (datetimeformatter, dateformatter, timeformatter)
521- plotly_convert_to_datetime(data, axis[:formatter])
522- else
523- data
524- end
514+ if ! isempty(axis[:discrete_values])
515+ map(
516+ xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)],
517+ data,
518+ )
519+ elseif axis[:formatter] in (datetimeformatter, dateformatter, timeformatter)
520+ plotly_convert_to_datetime(data, axis[:formatter])
521+ else
522+ data
523+ end
525524
526525plotly_convert_to_datetime(x:: AbstractArray , formatter:: Function ) =
527- if formatter == datetimeformatter
528- map(xi -> isfinite(xi) ? replace(formatter(xi), " T" => " " ) : missing , x)
529- elseif formatter == dateformatter
530- map(xi -> isfinite(xi) ? replace(formatter(xi), " T" => " " ) : missing , x)
531- elseif formatter == timeformatter
532- map(xi -> isfinite(xi) ? string(Dates. today(), " " , formatter(xi)) : missing , x)
533- else
534- error(
535- " Invalid DateTime formatter. Expected Plots.datetime/date/time formatter but got $formatter " ,
536- )
537- end
526+ if formatter == datetimeformatter
527+ map(xi -> isfinite(xi) ? replace(formatter(xi), " T" => " " ) : missing , x)
528+ elseif formatter == dateformatter
529+ map(xi -> isfinite(xi) ? replace(formatter(xi), " T" => " " ) : missing , x)
530+ elseif formatter == timeformatter
531+ map(xi -> isfinite(xi) ? string(Dates. today(), " " , formatter(xi)) : missing , x)
532+ else
533+ error(
534+ " Invalid DateTime formatter. Expected Plots.datetime/date/time formatter but got $formatter " ,
535+ )
536+ end
538537
539538# ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z)
540539as_gradient(grad:: ColorGradient , α) = grad
@@ -572,7 +571,7 @@ function plotly_series(plt::Plot, series::Series)
572571
573572 x, y, z = (
574573 plotly_data(series, letter, data) for
575- (letter, data) in zip((:x, :y, :z), (x, y, z))
574+ (letter, data) in zip((:x, :y, :z), (x, y, z))
576575 )
577576
578577 plotattributes_out[:name] = series[:label]
@@ -667,7 +666,7 @@ function plotly_series(plt::Plot, series::Series)
667666 plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
668667
669668 if series[:connections] != = nothing
670- if typeof(series[:connections]) <: Tuple{Array, Array, Array}
669+ if typeof(series[:connections]) <: Tuple{Array,Array,Array}
671670 # 0-based indexing
672671 i, j, k = series[:connections]
673672 if ! (length(i) == length(j) == length(k))
@@ -680,7 +679,7 @@ function plotly_series(plt::Plot, series::Series)
680679 plotattributes_out[:i] = i
681680 plotattributes_out[:j] = j
682681 plotattributes_out[:k] = k
683- elseif typeof(series[:connections]) <: AbstractVector{NTuple{3, Int}}
682+ elseif typeof(series[:connections]) <: AbstractVector{NTuple{3,Int}}
684683 # 1-based indexing
685684 i, j, k = broadcast(
686685 i -> [inds[i] - 1 for inds in series[:connections]],
@@ -722,19 +721,19 @@ function plotly_series(plt::Plot, series::Series)
722721 :size => 2_ cycle(series[:markersize], inds),
723722 :color =>
724723 rgba_string.(
725- plot_color.(
726- get_markercolor.(series, inds),
727- get_markeralpha.(series, inds),
724+ plot_color.(
725+ get_markercolor.(series, inds),
726+ get_markeralpha.(series, inds),
727+ ),
728728 ),
729- ),
730729 :line => KW(
731730 :color =>
732731 rgba_string.(
733- plot_color.(
734- get_markerstrokecolor.(series, inds),
735- get_markerstrokealpha.(series, inds),
732+ plot_color.(
733+ get_markerstrokecolor.(series, inds),
734+ get_markerstrokealpha.(series, inds),
735+ ),
736736 ),
737- ),
738737 :width => _cycle(series[:markerstrokewidth], inds),
739738 ),
740739 )
@@ -758,44 +757,34 @@ function plotly_colorbar(sp::Subplot)
758757end
759758
760759function plotly_series_shapes(plt:: Plot , series:: Series , clims)
761- segments = series_segments(series; check = true )
762- plotattributes_outs = map(i -> KW(), 1 : length(collect(segments)))
763-
764- # TODO : create a plotattributes_out for each polygon
765- # x, y = series[:x], series[:y]
766-
767- # these are the axes that the series should be mapped to
768- x_idx, y_idx = plotly_link_indicies(plt, series[:subplot])
769- plotattributes_base = KW(
770- :xaxis => " x$(x_idx) " ,
771- :yaxis => " y$(y_idx) " ,
772- :name => series[:label],
773- :legendgroup => series[:label],
774- )
775-
776- x, y = (
777- plotly_data(series, letter, data) for
778- (letter, data) in zip((:x, :y), shape_data(series, 100 ))
779- )
780-
781- for (k, segment) in enumerate(segments)
782- i, rng = segment. attr_index, segment. range
783- length(rng) < 2 && continue
760+ @show series[:x], series[:y]
761+ plotattributes_outs = KW[]
762+ i = 1
763+ for (xs, ys) in zip(nansplit(series[:x]), nansplit(series[:y]))
764+ # these are the axes that the series should be mapped to
765+ x_idx, y_idx = plotly_link_indicies(plt, series[:subplot])
766+ plotattributes_base = KW(
767+ :xaxis => " x$(x_idx) " ,
768+ :yaxis => " y$(y_idx) " ,
769+ :name => series[:label],
770+ :legendgroup => series[:label],
771+ )
784772
785773 # to draw polygons, we actually draw lines with fill
786774 plotattributes_out = merge(
787775 plotattributes_base,
788776 KW(
789777 :type => " scatter" ,
790778 :mode => " lines" ,
791- :x => vcat(x[rng], x[rng[ 1 ]]) ,
792- :y => vcat(y[rng], y[rng[ 1 ]]) ,
779+ :x => xs ,
780+ :y => ys ,
793781 :fill => " tozeroy" ,
794782 :fillcolor => rgba_string(
795783 plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
796784 ),
797785 ),
798786 )
787+ @show plotattributes_out
799788 if series[:markerstrokewidth] > 0
800789 plotattributes_out[:line] = KW(
801790 :color => rgba_string(
@@ -805,10 +794,11 @@ function plotly_series_shapes(plt::Plot, series::Series, clims)
805794 :dash => string(get_linestyle(series, i)),
806795 )
807796 end
808- plotattributes_out[:showlegend] = k == 1 ? should_add_to_legend(series) : false
797+ plotattributes_out[:showlegend] = i == 1 ? should_add_to_legend(series) : false
809798 plotly_polar!(plotattributes_out, series)
810799 plotly_adjust_hover_label!(plotattributes_out, _cycle(series[:hover], i))
811- plotattributes_outs[k] = merge(plotattributes_out, series[:extra_kwargs])
800+ push!(plotattributes_outs, merge(plotattributes_out, series[:extra_kwargs]))
801+ i += 1
812802 end
813803 if series[:fill_z] != = nothing
814804 push!(plotattributes_outs, plotly_colorbar_hack(series, plotattributes_base, :fill))
@@ -854,13 +844,13 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
854844 hasline ? " lines" : " none"
855845 end
856846 if series[:fillrange] == true ||
857- series[:fillrange] == 0 ||
858- isa(series[:fillrange], Tuple)
847+ series[:fillrange] == 0 ||
848+ isa(series[:fillrange], Tuple)
859849 plotattributes_out[:fill] = " tozeroy"
860850 plotattributes_out[:fillcolor] = rgba_string(
861851 plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
862852 )
863- elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real}, Real}
853+ elseif typeof(series[:fillrange]) <: Union{AbstractVector{<:Real},Real}
864854 plotattributes_out[:fill] = " tonexty"
865855 plotattributes_out[:fillcolor] = rgba_string(
866856 plot_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
@@ -902,9 +892,9 @@ function plotly_series_segments(series::Series, plotattributes_base::KW, x, y, z
902892 )
903893 lcolor_next =
904894 plot_color(
905- get_markerstrokecolor(series, i + 1 ),
906- get_markerstrokealpha(series, i + 1 ),
907- ) |> rgba_string
895+ get_markerstrokecolor(series, i + 1 ),
896+ get_markerstrokealpha(series, i + 1 ),
897+ ) |> rgba_string
908898
909899 plotattributes_out[:marker] = KW(
910900 :symbol => get_plotly_marker(
@@ -1022,12 +1012,12 @@ function plotly_colorbar_hack(series::Series, plotattributes_base::KW, sym::Symb
10221012end
10231013
10241014plotly_polar!(plotattributes_out:: KW , series:: Series ) =
1025- if ispolar(series[:subplot]) # convert polar plots x/y to theta/radius
1026- theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y)
1027- plotattributes_out[:theta] = rad2deg.(theta)
1028- plotattributes_out[:r] = r
1029- plotattributes_out[:type] = :scatterpolar
1030- end
1015+ if ispolar(series[:subplot]) # convert polar plots x/y to theta/radius
1016+ theta, r = pop!(plotattributes_out, :x), pop!(plotattributes_out, :y)
1017+ plotattributes_out[:theta] = rad2deg.(theta)
1018+ plotattributes_out[:r] = r
1019+ plotattributes_out[:type] = :scatterpolar
1020+ end
10311021
10321022function plotly_adjust_hover_label!(plotattributes_out:: KW , hover)
10331023 if hover === nothing
@@ -1056,11 +1046,11 @@ html_head(plt::Plot{PlotlyBackend}) = plotly_html_head(plt)
10561046html_body(plt:: Plot{PlotlyBackend} ) = plotly_html_body(plt)
10571047
10581048plotly_url() =
1059- if _use_local_dependencies[]
1060- _plotly_data_url()
1061- else
1062- " https://cdn.plot.ly/$_plotly_min_js_filename "
1063- end
1049+ if _use_local_dependencies[]
1050+ _plotly_data_url()
1051+ else
1052+ " https://cdn.plot.ly/$_plotly_min_js_filename "
1053+ end
10641054
10651055function plotly_html_head(plt:: Plot )
10661056 plotly = plotly_url()
0 commit comments