示例#1
0
    def _transform(self, element, transform_list):

        rows = 0

        if not transform_list:
            return element

        n_elements = len(transform_list)
        rows = n_elements % self.nrows
        cols = int(n_elements / self.nrows)

        if self.col_width is None:
            self.col_width = transform_list[0]['width']
        if self.row_height is None:
            self.row_height = transform_list[0]['height']

        for i in range(rows):
            element = GroupElement([element])
            element.moveto(0, self.row_height)

        for i in range(cols):
            element = GroupElement([element])
            element.moveto(self.col_width, 0)

        return element
示例#2
0
def _generate_grid(
        size: ElemSize, dxy: Length, width: float = 0.5, font_size: int = 8
) -> sc.Element:
    """
    Adapted from svgutils.compose.Grid
    
    Fills a rectangle with horizontal and vertical grid lines, spaced every `dxy` in both directions.

    Parameters
    ----------
    size : ElemSize
        The size of the rectangle to fill with grid lines
    dxy : Length
        The spacing of the grid lines, in units of size.unit
    width : float
        Line with of the grid lines
    font_size : int
        The size of the numbers marking each grid line. Set to zero for no labels.

    Returns
    -------
    svgutils.compose.Element
        The grid lines and labels
    """
    from svgutils.transform import LineElement, TextElement, GroupElement
    x, y = dxy, dxy
    lines = []
    txt = []
    units = size.units
    d_px = font_size
    width_px, height_px = units.to_px(size.width), units.to_px(size.height)
    while x <= size.width:
        x_px = units.to_px(x)
        lines.append(LineElement([(x_px, 0), (x_px, height_px)], width=width))
        txt.append(TextElement(x_px+d_px/2, d_px, str(x), size=font_size))
        x += dxy
    while y <= size.height:
        y_px = units.to_px(y)
        lines.append(LineElement([(0, y_px), (width_px, y_px)], width=width))
        txt.append(TextElement(d_px/2, y_px+d_px, str(y), size=font_size))
        y += dxy

    return sc.Element(GroupElement(txt+lines).root)
示例#3
0
def _compose_view(bg_svgs, fg_svgs, ref=0):

    if fg_svgs is None:
        fg_svgs = []

    # Merge SVGs and get roots
    svgs = bg_svgs + fg_svgs
    roots = [f.getroot() for f in svgs]

    # Query the size of each
    sizes = []
    for f in svgs:
        viewbox = [float(v) for v in f.root.get("viewBox").split(" ")]
        width = int(viewbox[2])
        height = int(viewbox[3])
        sizes.append((width, height))
    nsvgs = len(bg_svgs)

    sizes = np.array(sizes)

    # Calculate the scale to fit all widths
    width = sizes[ref, 0]
    scales = width / sizes[:, 0]
    heights = sizes[:, 1] * scales

    # Compose the views panel: total size is the width of
    # any element (used the first here) and the sum of heights
    fig = SVGFigure(width, heights[:nsvgs].sum())

    yoffset = 0
    for i, r in enumerate(roots):
        r.moveto(0, yoffset, scale=scales[i])
        if i == (nsvgs - 1):
            yoffset = 0
        else:
            yoffset += heights[i]

    # Group background and foreground panels in two groups
    if fg_svgs:
        newroots = [
            GroupElement(roots[:nsvgs], {"class": "background-svg"}),
            GroupElement(roots[nsvgs:], {"class": "foreground-svg"}),
        ]
    else:
        newroots = roots
    fig.append(newroots)
    fig.root.attrib.pop("width")
    fig.root.attrib.pop("height")
    fig.root.set("preserveAspectRatio", "xMidYMid meet")

    with TemporaryDirectory() as tmpdirname:
        out_file = Path(tmpdirname) / "tmp.svg"
        fig.save(str(out_file))
        # Post processing
        svg = out_file.read_text().splitlines()

    # Remove <?xml... line
    if svg[0].startswith("<?xml"):
        svg = svg[1:]

    # Add styles for the flicker animation
    if fg_svgs:
        svg.insert(
            2,
            """\
<style type="text/css">
@keyframes flickerAnimation%s { 0%% {opacity: 1;} 100%% { opacity: 0; }}
.foreground-svg { animation: 1s ease-in-out 0s alternate none infinite paused flickerAnimation%s;}
.foreground-svg:hover { animation-play-state: running;}
</style>""" % tuple([uuid4()] * 2),
        )

    return svg
示例#4
0
 def _transform(self, element, transform_list):
     for t in transform_list:
         element = GroupElement([element])
         element.moveto(0, t['height'])
     return element