Javascript 使用复选框之类的图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30663562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 05:33:13  来源:igfitidea点击:

Use images like checkboxes

javascriptjquerycsshtml

提问by bgs264

I would like to have an alternative to a standard checkbox - basically I'd like to use images and when the user clicks the image, fade it out and overlay a tick box.

我想有一个标准复选框的替代方案 - 基本上我想使用图像,当用户单击图像时,将其淡出并覆盖一个复选框。

In essence, I want to do something like Recaptcha 2 does when it gets you to click images that meet a certain criteria. You can see a Recaptcha demo herebut it might sometimes get you to solve text questions, as opposed to the image selection. So here's a screenshot:

本质上,我想做一些像 Recaptcha 2 那样的事情,当它让你点击满足特定条件的图像时。你可以在这里看到一个 Recaptcha 演示,但它有时可能会让你解决文本问题,而不是图像选择。所以这是一个截图:

Google Recaptcha screenshot

Google Recaptcha 屏幕截图

When you click one of the images (in this case, containing a picture of steak), the image you click shrinks in size and the blue tick appears, indicating that you've ticked it.

当您单击其中一个图像(在本例中,包含一张牛排图片)时,您单击的图像会缩小尺寸并出现蓝色勾号,表明您已勾选它。

Let's say I want to reproduce this exact example.

假设我想重现这个确切的例子。

I realise I can have 9 hidden checkboxes, and attach some jQuery so that when I click the image, it selects/deselects the hidden checkbox. But what about the shrinking of the image/overlaying the tick?

我意识到我可以有 9 个隐藏的复选框,并附加一些 jQuery 以便当我单击图像时,它选择/取消选择隐藏的复选框。但是图像的缩小/覆盖刻度线呢?

回答by connexo

Pure semantic HTML/CSS solution

纯语义 HTML/CSS 解决方案

This is easy to implement on your own, no pre-made solution necessary. Also it will teach you a lot as you don't seem too easy with CSS.

这很容易自己实现,不需要预先制定的解决方案。此外,它会教你很多东西,因为你对 CSS 似乎不太容易。

This is what you need to do:

这是你需要做的:

Your checkboxes need to have distinct idattributes. This allows you to connect a <label>to it, using the label's for-attribute.

您的复选框需要具有不同的id属性。这允许您<label>使用标签的 -for属性将 a 连接到它。

Example:

例子:

<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1"><img src="http://someurl" /></label>

Attaching the label to the checkbox will trigger a browser behaviour: Whenever someone clicks the label (or the image inside it), the checkbox will be toggled.

将标签附加到复选框将触发浏览器行为:每当有人单击标签(或其中的图像)时,复选框将被切换。

Next, you hide the checkbox by applying for example display: none;to it.

接下来,您通过应用例如display: none;来隐藏复选框。

Now all that is left to do is set the style you want for your label::beforepseudo element (which will be used as the visual checkbox replacement elements):

现在剩下要做的就是为label::before伪元素设置所需的样式(将用作可视复选框替换元素):

label::before {
    background-image: url(../path/to/unchecked.png);
}

In a last tricky step, you make use of CSS' :checkedpseudo selector to change the image when the checkbox is checked:

在最后一个棘手的步骤中,您使用 CSS 的:checked伪选择器在选中复选框时更改图像:

:checked + label::before {
    background-image: url(../path/to/checked.png);
}

The +(adjacent sibling selector) makes sure you only change labels that directly follow the hidden checkbox in the markup.

+相邻兄弟选择器)可确保您只更改标签直接按照标记隐藏复选框。

You can optimize that by putting both images in a spritemap and only applying a change in background-positioninstead of swapping the image.

您可以通过将两个图像放在一个 spritemap 中并仅应用更改background-position而不是交换图像来优化它。

Of course you need to position the label correctly and apply display: block;and set correct widthand height.

当然,您需要正确display: block;放置标签并应用和设置正确的widthheight

Edit:

编辑:

The codepen example and snippet, which I created after these instructions, use the same technique, but instead of using images for the checkboxes, the checkbox replacements are done purely with CSS, creating a ::beforeon the label that, once checked, has content: "?";. Add some rounded borders and sweet transitions and the result is really likable!

我在这些说明之后创建的 codepen 示例和代码段使用相同的技术,但不是使用图像作为复选框,复选框替换完全使用 CSS 完成::before在标签上创建一个,一旦选中,就会有content: "?";. 添加一些圆形边框和甜美的过渡效果,结果非常讨人喜欢!

Here is a working codepen that showcases the technique and doesn't require images for the checkbox:

这是一个展示该技术的工作代码笔,不需要复选框的图像:

http://codepen.io/anon/pen/wadwpx

http://codepen.io/anon/pen/wadwpx

Here is the same code in a snippet:

这是一个片段中的相同代码:

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

input[type="checkbox"][id^="cb"] {
  display: none;
}

label {
  border: 1px solid #fff;
  padding: 10px;
  display: block;
  position: relative;
  margin: 10px;
  cursor: pointer;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

label::before {
  background-color: white;
  color: white;
  content: " ";
  display: block;
  border-radius: 50%;
  border: 1px solid grey;
  position: absolute;
  top: -5px;
  left: -5px;
  width: 25px;
  height: 25px;
  text-align: center;
  line-height: 28px;
  transition-duration: 0.4s;
  transform: scale(0);
}

label img {
  height: 100px;
  width: 100px;
  transition-duration: 0.2s;
  transform-origin: 50% 50%;
}

:checked+label {
  border-color: #ddd;
}

:checked+label::before {
  content: "?";
  background-color: grey;
  transform: scale(1);
}

:checked+label img {
  transform: scale(0.9);
  box-shadow: 0 0 5px #333;
  z-index: -1;
}
<ul>
  <li><input type="checkbox" id="cb1" />
    <label for="cb1"><img src="https://picsum.photos/seed/1/100" /></label>
  </li>
  <li><input type="checkbox" id="cb2" />
    <label for="cb2"><img src="https://picsum.photos/seed/2/100" /></label>
  </li>
  <li><input type="checkbox" id="cb3" />
    <label for="cb3"><img src="https://picsum.photos/seed/3/100" /></label>
  </li>
  <li><input type="checkbox" id="cb4" />
    <label for="cb4"><img src="https://picsum.photos/seed/4/100" /></label>
  </li>
</ul>

回答by jcuenod

Pure CSS Solution

纯 CSS 解决方案

There are three neat devices invoked:

调用了三个简洁的设备:

  1. The :checkedselector
  2. The ::beforepseudo-selector
  3. The css contentproperty.
  1. :checked选择
  2. ::before伪选择
  3. csscontent属性。

label:before {
  content: url("https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/unchecked_checkbox.png");
  position: absolute;
  z-index: 100;
}
:checked+label:before {
  content: url("https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/checked_checkbox.png");
}
input[type=checkbox] {
  display: none;
}
/*pure cosmetics:*/
img {
  width: 150px;
  height: 150px;
}
label {
  margin: 10px;
}
<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1">
  <img src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcR0LkgDZRDTgnDrzhnXGDFRSItAzGCBEWEnkLMdnA_zkIH5Zg6oag">
</label>
<input type="checkbox" id="myCheckbox2" />
<label for="myCheckbox2">
  <img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRhJjGB3mQxjhI5lfS9SwXou06-2qT_0MjNAr0atu75trXIaR2d">
</label>
<input type="checkbox" id="myCheckbox3" />
<label for="myCheckbox3">
  <img src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQuwWbUXC-lgzQHp-j1iw56PIgl_2eALrEENUP-ld72gq3s8cVo">
</label>

回答by jcuenod

See this jQuery plugin: imgCheckbox(on npmand bower)

请参阅此 jQuery 插件:imgCheckbox(在npmbower 上

Disclaimer:No javascript is necessary to solve this problem.?The tension is between maintainability and efficiency of code. While there's no need for a plugin (or any javascript), it sure does make it faster to build and often easier to change.

免责声明:解决这个问题不需要javascript。?可维护性和代码效率之间的紧张关系。虽然不需要插件(或任何 javascript),但它确实可以更快地构建并且通常更容易更改。

Barebones Solution:

准系统解决方案:

With very simple HTML(none of the mess with checkboxes and labels etc.):

使用非常简单的 HTML(没有复选框和标签等的混乱):

<img class="checkable" src="http://lorempixel.com/100/100" />

You can use jQuery's toggleClassto turn on/off a selectedor checkedclass on the clickevent:

您可以使用 jQuery 的toggleClass来打开/关闭事件上的selectedcheckedclick

$("img.checkable").click(function () {
    $(this).toggleClass("checked");
});

Checked items are fetched with

被检查的项目是用

$(".checked")

Plus Coolness:

加凉:

You can style the images based off of this but a big problem is that without other DOM?elements you can't even use ::beforeand ::afterto add stuff like check marks. The solution is to wrap your images with another element (and it makes sense to attach the click listener to the wrapped element as well).

您可以基于此设置图像样式,但一个大问题是,如果没有其他 DOM?元素,您甚至无法使用::before::after添加诸如复选标记之类的东西。解决方案是用另一个元素包装您的图像(并且将点击侦听器附加到包装元素也是有意义的)。

$("img.checkable").wrap("<span class='fancychecks'>")

This leaves your html really clean and your js incredibly readable. Take a look at the snippet...

这使您的 html 非常干净,并且您的 js 非常可读。看看片段...

/* Note that this js actually responds
   to a click event on the wrapped element!
   (not the image) */
$("img.checkable").wrap("<span class='fancychecks'>")
  .parent().click(function() {
    $(this).toggleClass("checked");
  });
/* style the images */
span.fancychecks img {
  display: block;
  margin: 0;
  padding: 0;
  transition-duration: 300ms;
  transform: scale(1);
  filter: none;
  -webkit-filter: grayscale(0);
}
span.fancychecks.checked img {
  transform: scale(0.8);
  filter: gray;
  filter: grayscale(1);
  -webkit-filter: grayscale(1);
}

/* style the parent spans */
span.fancychecks {
  padding: 0;
  margin: 5px;
  display: inline-block;
  border: 1px solid transparent;
  transition-duration: 300ms;
}
span.fancychecks.checked {
  border-color: #ccc;
}

/* Using conexo's fantastic CSS, make the checkmarks */
span.fancychecks::before {
  background-color: rgba(50, 200, 50, 0.7);
  color: white;
  content: "?";
  font-weight: bold;
  border-radius: 50%;
  position: absolute;
  margin: 2px;
  top: 1;
  left: 1;
  z-index: 1;
  width: 25px;
  height: 25px;
  text-align: center;
  line-height: 28px;
  transform: scale(0);
  transition-duration: 300ms;
}
span.fancychecks.checked::before {
  transform: scale(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<img class="checkable" src="http://lorempixel.com/100/100/city/1" />
<img class="checkable" src="http://lorempixel.com/100/100/city/2" />
<img class="checkable" src="http://lorempixel.com/100/100/city/3" />

Using the imgCheckboxjQuery Plugin:

使用imgCheckboxjQuery 插件:

Inspired by the solution above, I have built a plugin which can be used as easily as:

受上述解决方案的启发,我构建了一个插件,可以像以下那样轻松使用:

$("img").imgCheckbox();
  • Injects the data for checked images into your form
  • Supports custom check marks
  • Supports customised CSS
  • Supports preselected elements
  • Supports radio groups instead of simple toggling of images
  • Has event callbacks
  • Sensible defaults
  • Lightweight and super easy to use
  • 将检查图像的数据注入表单
  • 支持自定义复选标记
  • 支持自定义 CSS
  • 支持预选元素
  • 支持无线电组而不是简单的图像切换
  • 有事件回调
  • 合理的默认值
  • 轻巧且超级易于使用

See it in action(and see the source)

看到它在行动(并看到源

回答by Cagatay Ulubay

I would append an extra div with position: relative;and class="checked"which has the same width/height as the image has and than position in left: 0; top: 0;containing the icon. It starts with display: none;.

我想追加额外的分度,position: relative;class="checked"具有相同的宽度/高度,该图像具有与比在位置left: 0; top: 0;包含图标。它以 开头display: none;

Now you can listen to the click-event:

现在您可以收听click-event:

$( '.captcha_images' ).click( function() {
    $(this + '.checked').css( 'display', 'block' );
    $(this).animate( { width: '70%', height: '70%' } );
});

This way you can get the icon and also resize the image to a smaller way.

通过这种方式,您可以获得图标并将图像调整为更小的方式。

Notice: Just wanted to show you the "logic" behind my thoughts, this example might not work or has some bugs in it.

注意:只是想向您展示我的想法背后的“逻辑”,此示例可能不起作用或存在一些错误。

回答by rybo111

I've noticed other answers either don't use <label>(why not?), or require matching forand idattributes. This means if you have clashing IDs, your code won't work, and you must remember to make unique IDs each time.

我注意到其他答案要么不使用<label>(为什么不使用?),要么需要匹配forid属性。这意味着如果您有冲突的 ID,您的代码将无法工作,您必须记住每次都制作唯一的 ID。

Also, if you hide the inputwith display:noneor visibility:hidden, the browser will not focus on it.

此外,如果您隐藏inputwithdisplay:nonevisibility:hidden,浏览器将不会关注它。

A checkbox and its text (or in this case, image) can be wrapped in a label:

复选框及其文本(或在本例中为图像)可以包含在标签中:

.fancy-checkbox-label > input[type=checkbox] {
  position: absolute;
  opacity: 0;
  cursor: inherit;
}
.fancy-checkbox-label {
  font-weight: normal;
  cursor: pointer;
}
.fancy-checkbox:before {
  font-family: FontAwesome;
  content: "\f00c";
  background: #fff;
  color: transparent;
  border: 3px solid #ddd;
  border-radius: 3px;
  z-index: 1;
}
.fancy-checkbox-label:hover > .fancy-checkbox:before,
input:focus + .fancy-checkbox:before {
  border-color: #bdbdff;
}
.fancy-checkbox-label:hover > input:not(:checked) + .fancy-checkbox:before {
  color: #eee;
}
input:checked + .fancy-checkbox:before {
  color: #fff;
  background: #bdbdff;
  border-color: #bdbdff;
}
.fancy-checkbox-img:before {
  position: absolute;
  margin: 3px;
  line-height: normal;
}
input:checked + .fancy-checkbox-img + img {
  transform: scale(0.9);
  box-shadow: 0 0 5px #bdbdff;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
<p>
  <label class="fancy-checkbox-label">
    <input type="checkbox">
    <span class="fancy-checkbox"></span>
    A normal checkbox
  </label>
</p>
<p>
  <label class="fancy-checkbox-label">
    <input type="checkbox">
    <span class="fancy-checkbox fancy-checkbox-img"></span>
    <img src="http://placehold.it/150x150">
  </label>
</p>

回答by YaBCK

Here a quick example of selecting an image like a checkbox

这是选择复选框等图像的快速示例

Updated Example using Knockout.js:

使用 Knockout.js 的更新示例:

var imageModel = function() {
    this.chk = ko.observableArray();
};
ko.applyBindings(new imageModel());
    input[type=checkbox] {
        display:none;
      }
 
  input[type=checkbox] + label
   {
       display:inline-block;
        width:150px;
        height:150px;
        background:#FBDFDA;
        border:none;
   }
   
   input[type=checkbox]:checked + label
    {
        background:#CFCFCF;
        border:none;
        position:relative;
        width:100px;
        height:100px;
        padding: 20px;
    }

   input[type=checkbox]:checked + label:after
    {
        content: '13';
        position:absolute;
        top:-10px;
        right:-10px;
        border-radius: 10px;
        width: 25px;
        height: 25px;
        border-color: white;
        background-color: blue;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<input type='checkbox' name='image1' value='image1' id="image1" data-bind="checked: chk"/><label for="image1"></label><label for="image1"><img class='testbtn'/></label>

<div data-bind="html: chk"></div>

回答by essexboyracer

To expand on the accepted answer for anyone using WordPress & GravityForms to generate their forms and wish to automatically populate checkbox fields with a list of posts and their associated Featured Thumbnail

为使用 WordPress 和 GravityForms 生成表单并希望自动填充带有帖子列表及其相关精选缩略图的复选框字段的任何人扩展已接受的答案

// Change '2' to your form ID
add_filter( 'gform_pre_render_2', 'populate_checkbox' );
add_filter( 'gform_pre_validation_2', 'populate_checkbox' );
add_filter( 'gform_pre_submission_filter_2', 'populate_checkbox' );
add_filter( 'gform_admin_pre_render_2', 'populate_checkbox' );

function populate_checkbox( $form ) {

    foreach( $form['fields'] as &$field )  {

        // Change '41' to your checkbox field ID
        $field_id = 41;
        if ( $field->id != $field_id ) {
            continue;
        }

        // Adjust $args for your post type
        $args = array(
                'post_type' => 'pet',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'tax_query' => array(
                        array(
                                'taxonomy' => 'pet_category',
                                'field' => 'slug',
                                'terms' => 'cat'
                        )
                )
        );

        $posts = get_posts( $args );

        $input_id = 1;

        foreach( $posts as $post ) {

            $feat_image_url = wp_get_attachment_image( get_post_thumbnail_id( $post->ID ), 'thumbnail' );
            $feat_image_url .= '<br />' . $post->post_title;

            if ( $input_id % 10 == 0 ) {
                $input_id++;
            }

            $choices[] = array( 'text' => $feat_image_url, 'value' => $post->post_title );
            $inputs[] = array( 'label' => $post->post_title, 'id' => "{$field_id}.{$input_id}" );

            $input_id++;
        }

        $field->choices = $choices;
        $field->inputs = $inputs;

    }

    return $form;
}

And the CSS:

和 CSS:

.gform_wrapper .gfield_checkbox li[class^="gchoice_2_41_"] {
    display: inline-block;
}

.gform_wrapper .gfield_checkbox li input[type="checkbox"][id^="choice_2_41_"] {
    display: none;
}


.gform_wrapper .gfield_checkbox li label[id^="label_2_41_"] {
    border: 1px solid #fff;
    padding: 10px;
    display: block;
    position: relative;
    margin: 10px;
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

label[id^="label_2_41_"]:before {
    font-family: "font-icons";
    font-size: 32px;
    color: #1abc9c;
    content: " ";
    display: block;
    background-color: transparent;
    position: absolute;
    top: -5px;
    left: -5px;
    width: 25px;
    height: 25px;
    text-align: center;
    line-height: 28px;
    transition-duration: 0.4s;
    transform: scale(0);
}

label[id^="label_2_41_"] img {
    transition-duration: 0.2s;
    transform-origin: 50% 50%;
}

:checked + label[id^="label_2_41_"] {
    border-color: #ddd;
}

/* FontAwesome tick */
:checked + label[id^="label_2_41_"]:before {
    content: "\e6c8";
    background-color: transparent;
    transform: scale(1);
}

:checked + label[id^="label_2_41_"] img {
    transform: scale(0.9);
    box-shadow: 0 0 5px #333;
    z-index: 0;
}