使用jQuery和CSS设置外部SVG文件的样式

时间:2016-11-23 作者:CoderScissorhands

我已经在我的WP站点上使用启用了SVG文件链接Safe SVG plug-in, 我对此非常满意。但是,我在设置包含在调用/linink的外部文件中的SVG路径的样式时遇到了问题。目前,我无法创建所需的互动性,因为我无法:

使用我的自定义javascript/jQuery向各个SVGPath添加类(它适用于我的所有内联SVG,而不是外部链接的SVG)当我使用内联SVG时,我可以按照我想要的方式控制一切,我的jQuery和CSS工作。但是,当我使用安全的SVG插件使用外部文件时,我的CSS似乎不会与路径元素交互,也不会修改它们。

我已经找到了关于CSS和外部SVG(例如this), 但我想知道这里是否有人可能有一个高效、简单的基于WordPress的解决方案,允许1)我的jQuery脚本访问和修改路径类,2)我的CSS修改路径元素。

我意识到我只是走内联路线,省去了麻烦,但我有理由想看看我是否不能用独立的SVG文件来完成这一点。

谢谢

2 个回复
最合适的回答,由SO网友:CoderScissorhands 整理而成

I have found two imperfect but functional solutions, each with its own limitations.

Please note, before you can employ either of the solutions, you will need to enable SVG uploading to your page first (as WP does not allow it by default). You can do this by using a plugin like Safe SVG.

The solution I chose in the end actually doesn\'t require any jQuery at all. It involves using a popular WP plug-in called "Advanced Custom Fields" (or ACF) and adding some php to your templates. The second solution is one which I found in one of the SVG discussion threads posted by socki03 in a different question (which I happened to have asked); it uses a jQuery library called SVGinjector.

Solution #1: Advanced Custom Fields(ACF)

This solution is the one I chose to implement, and I found it in this discussion thread. It isn\'t ideal because you have to add some code explicitly to your templates, (instead of being able to add everything in in the WP dashboard). So, If you go this route, you should to know a bit about editing template files.

What the ACF solution does

Once you set-up the ACF plug-in appropriately and place the code in your template, you will field in your dashboard which you allows you to select an SVG file. It is great because that SVG is really a part of the page, which is modifyiable with CSS, and loads with all of the other elements early on.

How to implement it

  1. Install the ACF plugin.
  2. Using the ACF-plugin, follow the steps to create an image field that returned the image URL.

    2.1. go to the dashboard

    2.2. select the custom fields section (it is part of the ACF plugin)

    2.3. at the top of the page it says "Field Groups", select the "add new" button next to it.

    2.4. Create the field

    • 2.4.1. designate the "field name", and the select the appropriate options. You need to making sure to select the "image" for the "field type" option.

    • 2.4.2. After you select "image" from the "field type" options, a new option, "Return URL", will appear. It is that option that is going to generate the code that will grab your images. Choose "Return URL"

3.Open the php file for the template you want to add the svg to.

  1. Inside your php file, insert this code anywhere you want the SVG to appear: <?php echo file_get_contents( get_field( \'the_svg_field_name_you_designated\' ) ); ?> and save your file.

  2. Go back to the WP dashboard, go to "pages", and navigate to the "edit" screen for the page you want the SVG to appear in. You should now have field with the "field name" you entered that will you to select an image.

  3. Click on the button near the field name, it should then prompt you to navigate your files. Navigate to the SVG file you want to upload, and select it.

  4. Click on "Update" to finalize the SVG insertion. You should now have SVGs that load as part of the page, which you can edit/stylize with CSS.

Pros:

The code that inserts the SVG executes as the page loads, so the SVG element is part of the foundations fo the page, rather than being "added-on" later (whic is the problem with the other solution).

Cons:

Because the SVG is called from a separate file, and not combined in any meaingful way with other code on the page, all of the classes must be manually inserted into the SVG file. That means if you want to have two different versions of the same SVG, with different classes, you have two use two different files. However, you can work around this limitation, and still use the same file for two differently styled SVGs, by editing the parent classes in the templages and then using those classes to stylize the two different files (e.g. .parentForStyle1 svg and .parentForStyle2 svg).

Also, with this method you have to modify your code a bit more, than in the other case, but it really isn\'t too bad.

Solution #2: SVGInjector

This did what I wanted, in that it allowed me to add SVGs that are visible to the DOM and stylizable with CSS, but it has one problem. Because it uses an enqueued script, it doesn\'t run until after the page has loaded the other elements. As such, can cause weird shifts/blinks while the page loads and and after excutes.

What SVGinjector does

When implemented, SVGinjector:

  1. calls a separate SVG file as an img element;
  2. uses javascript to parse the SVG and inject the SVG as an inline element; visible to the DOM.
  3. allows the designer to employ CSS to stylize the individual SVG paths/elements.
  4. converts the img element to an svg element, and combines any header info from the existing img tag and the SVG-file into the SVG-tag.

How to implement it

  1. In your template file, add a class called inject-me to your img element where you want to have the SVG drawn, and in the img tag link the SVG file to the img using data-src instead of src. Here is the working code I put in my template file: <img class="funkyLogo inject-me" data-src="<?php echo $logoImg; ?>" alt="logo" />
  2. enqueue the js script "svg-injector.min.js" (which is in the SVG injector .zip file) in your "functions.php", along with your custom js:

    function mytheme_enqueue_front_page_scripts() {
    if( is_front_page() )
    {
        wp_enqueue_script( \'myJq\', "/js/jquery-1.10.2.min.js", array( \'jquery\' ), null, true );
        wp_enqueue_script( \'injectSVG\', get_stylesheet_directory_uri() . \'/js/svg-injector.min.js\', array( \'jquery\' ), null, true );
        wp_enqueue_script( \'custom\', get_stylesheet_directory_uri() . \'/js/custom.js\', array( \'jquery\' ), null, true );

    } } add_action( \'wp_enqueue_scripts\', \'mytheme_enqueue_front_page_scripts\' );

  3. include the following code in your "custom.js" file

    //For testing in IE8
    if (!window.console){ console = {log: function() {}}; };
    
    // Elements to inject
      var mySVGsToInject = document.querySelectorAll(\'img.inject-me\');
    
    // Options
      var injectorOptions = {
        evalScripts: \'once\',
        pngFallback: \'assets/png\',
        each: function (svg) {
          // Callback after each SVG is injected
          if (svg) console.log(\'SVG injected: \' + svg.getAttribute(\'id\'));
        }
      };
    
      // Trigger the injection
      SVGInjector(mySVGsToInject, injectorOptions, function (totalSVGsInjected) {
        // Callback after all SVGs are injected
        console.log(\'We injected \' + totalSVGsInjected + \' SVG(s)!\');
      });
    

Pros:

It is simple, uses an img tag, and it is easy to edit classes in templates

Cons:

the SVGs are drawn later in the page drawing process, and this can cause weird rendering effects/blinking/changes in the pages while loading. I am currently using customizer and have my SVG designated as my header logo. Maybe it is happening because data-src tag is confusing Wordpress, so before the js for SVG runs, the theme temporarily shows the alt designated text "logo" in the img tag. If I remove the alt text, the div is empty for about half a second before the SVG is injected, but this causes an odd and undesirable shifting of elements on the page during the injection.

Alternately, the issue might have to do with order in which js is execute when drawing the page. I have learned that enqueued js always runs after page loading, so the fact that this is controlled via js, at the end of the loading process is very likely what is causing the blink. If someone can suggest a solution for that uses SVG injector, but doesn\'t cause a blink, it would be nice to see it.

SO网友:socki03

很抱歉,但这是不可能的,因为SVG中的任何元素都不会在DOM中读取,所以CSS和Javascript看不到它们。它看到的只是<img> 块,没有其内容。您必须将SVG导入到页面中,才能对其进行操作。

查看CSS Tricks article on SVGs