Как мне назначить прослушиватель событий angularjs внутри цикла ng-repeat?

Я новичок в angularjs. Я пытаюсь создать фотогалерею, где начальная страница представляет собой лист миниатюрных фотографий из twitter и instagram, созданных с помощью цикла angularjs ng-repeat. Когда пользователь наводит курсор на изображение, изображение исчезает и появляется кнопка, которую пользователь может нажать. Я создал эффект наведения с помощью ng-mouseenter и ng-mouseleave. Но по какой-то причине, когда я наводил указатель мыши на изображение, это затрагивает все изображения. Только одно изображение, на которое я наведен, должно быть нацелено. Я не уверен, что сделал не так. Пожалуйста помоги! Код ниже. Также вот ссылка на код онлайн: http://www.petermingione.com/my-demo/

<style>
        * {
            box-sizing: border-box;
            font-family: sans-serif;
        }
        h1, 
        h2{
            margin-left:10px;
        }
        .inner{
            display:inline-block;
            vertical-align:top;
            padding:5px;
            position:relative;
        }
        .inner img{
            width:100%;
        }
        .inner .outer-caption{
            color:black;
            width:375px;
            height:125px;
            background-color:#fc7cab;
            display:flex;
        }
        .inner .outer-caption .inner-caption{
            font-size:14px;
            font-family:sans-serif;
            overflow:hidden;
            width:320px;
            height:70px;
            margin:auto;
        }
        .inner .overlay-color{
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            margin:auto;
            background-color: #fff;
            transition: all .5s;    
        }
        .inner .overlay-text{
            border: 2px solid #7e7e7e;
            color:#7e7e7e;
            font-size: 10px;
            position: absolute;
            top:0;
            bottom:0;
            left:0;
            right:0;
            width:70px;
            height:35px;
            line-height:35px;
            margin:auto;
            border-radius:1px;
            text-align: center;
            transition: all .5s;

    </style>

<body>  
    <h1>{{title}}</h1> 
    <h2>{{myMessage}}</h2>
    <div id = "outer" class = "outer">
        <div class = "inner" ng-mouseenter = "makeVisibile()" ng-mouseleave = "makeInVisibile()" ng-repeat = "x in insideData">
            <img ng-if = "x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
             <div ng-if = "x.service=='Twitter'&& x.mediaType!='image'" class = "outer-caption"><div class = "inner-caption">{{x.caption}}</div></div>
            <div class = "overlay-color" ng-style = "overlayColorStyles" ></div>
            <div class = "overlay-text" ng-style = "overlayTextStyles">VIEW</div>
        </div>
    </div>

<script>

    // Create the module
    var appModule = angular.module('appName', []);

    // Create rootScope variables
    appModule.run(
        function($rootScope){
            $rootScope.title = "Taneleer Demonstration";
        }
    );

    // Create the controller
    appModule.controller('appCtrl', function($scope, $http) {

        $scope.overlayColorStyles = {"opacity": 0};
        $scope.overlayTextStyles =  {"opacity": 0};

        $scope.makeVisibile = function(){
            //alert("test"); 
            //document.getElementById("overlay-color").style.opacity = .75;
            //document.getElementById("overlay-text").style.opacity = 1;
            $scope.overlayColorStyles = {"opacity" : .75};
            $scope.overlayTextStyles = {"opacity" : 1};

        }
        $scope.makeInVisibile = function(){
            //alert("test"); 
            //document.getElementById("overlay-color").style.opacity = 0;
            //document.getElementById("overlay-text").style.opacity = 0;
            $scope.overlayColorStyles = {"opacity" : 0};
            $scope.overlayTextStyles = {"opacity" : 0};

        }

        $http({
                method : "GET",
                url : "https://taneleer.composedcreative.com/api/v1/feed/a0329f16-9225-11e6-89bb-296a97b9d609/bb0429f6-f0ca-11e7-8f5d-d92739a9a53f"
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";

                $scope.response = response;
                $scope.meta = response.data.meta;
                $scope.outsideData = response.data;
                $scope.insideData = response.data.data;
                $scope.links = response.data.links;

                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });


        $scope.getNext = function() {
            $http({
                method : "GET",
                url : $scope.nextLink
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";
                $scope.response = response;
                $scope.outsideData = response.data;
                $scope.meta = response.data.meta;

                $scope.insideData = $scope.insideData.concat(response.data.data);

                $scope.links = response.data.links;
                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });
        }
        $(window).scroll(function() {
            if ($(window).scrollTop() + $(window).height() == $(document).height()) {
                $scope.getNext();
            }
        });
    });

</script>

Привет, Еще раз спасибо за ответ Аарон. У меня есть еще одна проблема, которую мне нужно решить. Сейчас я создаю часть приложения со световым коробом. Это наложение, которое вы видите, когда нажимаете кнопку просмотра. Я разместил последнюю версию здесь в Интернете: http://www.petermingione.com/my-demo/ Как видите, независимо от того, на каком изображении вы нажимаете, единственное изображение, которое появляется, является первым изображением в коллекции. Опять же, это еще одна проблема с ng-repeat. Изображение находится в каждом объекте как mainImage.url, и я получаю к нему доступ через x.mainImage.url в цикле ng-repeat. Я не уверен, почему это не работает. Любая помощь, которую кто-либо может мне дать, будет принята с благодарностью. Код находится ниже и в Интернете:

   <style>
    * {
        box-sizing: border-box;
        font-family: sans-serif;
    }
    h1, 
    h2{
        margin-left:10px;
    }

    .outer-wrapper{
        overflow: hidden;
    }
    .inner-wrapper{
        display:inline-block;
        vertical-align:top;
        padding:5px;
        position:relative;
    }
    .inner-wrapper img{
        width:100%;
    }
    .inner-wrapper .outer-caption{
        color:black;
        width:100%;
        padding-top:35%;
        background-color:#fc7cab;
        position:relative;
    }
    .inner-wrapper .outer-caption .inner-caption{
        font-size:14px;
        font-family:sans-serif;
        overflow:hidden;
        width:75%;
        height:70px;
        position:absolute;
        top:0;
        left:0;
        bottom:0;
        right:0;
        margin:auto;
    }
    .inner-wrapper .item-overlay-color{
        position: absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        margin:auto;
        background-color: #fff;
        transition: all .5s;
        opacity: 0.0;   
    }
    .inner-wrapper:hover .item-overlay-color {
        opacity: 0.75;
    }
    .inner-wrapper .item-overlay-text{
        border: 2px solid #7e7e7e;
        color:#7e7e7e;
        font-size: 10px;
        position: absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        width:70px;
        height:35px;
        line-height:35px;
        margin:auto;
        border-radius:1px;
        text-align: center;
        transition: all .5s;
        opacity: 0.0;
    }
    .inner-wrapper:hover .item-overlay-text {
        opacity: 1.0;
    }
    .inner-wrapper .page-overlay {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0; 
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(255,255,255,0.75);
        z-index: 2;
        cursor: pointer;
    }
    .inner-wrapper #page-overlay {
        opacity:0;
        transition: all .5s;
        pointer-events:none;
    }
    .inner-wrapper .page-overlay .text{
        position: absolute;
        top: 50%;
        left: 50%;
        font-size: 50px;
        color: white;
        transform: translate(-50%,-50%);
        -ms-transform: translate(-50%,-50%);
    }
    .inner-wrapper .page-overlay .text .close{
        position:absolute;
        top:0;
        right:0;
        color:#000;
        font-weight: lighter;
        font-size: 30px;
        line-height: 30px;
        padding-top:5px;
        padding-right:5px;
    }

    @media screen and (min-width: 1301px){
        .inner-wrapper{
            width:16.6666%;
        }
    }
    @media screen and (max-width: 1300px){
        .inner-wrapper{
            width:20%;
        }
    }
    @media screen and (max-width: 1024px){
        .inner-wrapper{
            width:25%;
        }
    }
    @media screen and (max-width: 768px){
        .inner-wrapper{
            width:50%;
        }
    }
    @media screen and (max-width: 480px){
        .inner-wrapper{
            width:100%;
        }
    }

  </style>

 <body>
<div id = "outer-wrapper" class = "outer-wrapper">
    <div id = "inner-wrapper" class = "inner-wrapper" ng-repeat = "x in insideData">
        <img ng-if = "x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
        <div class = "outer-caption" ng-if = "x.service=='Twitter'&& x.mediaType!='image'">
            <div class = "inner-caption">{{x.caption}}</div>
        </div>
        <div class = "item-overlay-color"></div>
        <div class = "item-overlay-text" ng-click = "showOverlay()">VIEW</div>
        <div id = "page-overlay" class = "page-overlay">
                <div class = "text">
                    <img ng-src='{{x.mainImage.url}}'>
                    <span class = "close" ng-click = "hideOverlay()">X</span>
                </div>
        </div>
    </div>
</div>
 </body>
  <script>
    // Create the module
    var appModule = angular.module('appName', []);

    // Create rootScope variables
    appModule.run(
        function($rootScope){
            $rootScope.title = "Taneleer Demonstration";
        }
    );

    // Create the controller
    appModule.controller('appCtrl', function($scope, $http) {

        $scope.showOverlay = function(){
            document.getElementById("page-overlay").style.opacity = 1;
            document.getElementById("page-overlay").style["pointer-events"] = "auto";
        }
        $scope.hideOverlay = function(){
            document.getElementById("page-overlay").style.opacity = 0;
            document.getElementById("page-overlay").style["pointer-events"] = "none";
        }

        $http({
                method : "GET",
                url : "https://taneleer.composedcreative.com/api/v1/feed/a0329f16-9225-11e6-89bb-296a97b9d609/bb0429f6-f0ca-11e7-8f5d-d92739a9a53f"
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";

                $scope.response = response;
                $scope.meta = response.data.meta;
                $scope.outsideData = response.data;
                $scope.insideData = response.data.data;
                $scope.links = response.data.links;

                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });


        $scope.getNext = function() {
            $http({
                method : "GET",
                url : $scope.nextLink
            }).then(function mySucces(response) {

                $scope.myMessage = "Success!";
                $scope.response = response;
                $scope.outsideData = response.data;
                $scope.meta = response.data.meta;

                $scope.insideData = $scope.insideData.concat(response.data.data);

                $scope.links = response.data.links;
                $scope.selfLink = response.data.links.self;
                $scope.firstLink = response.data.links.first;
                $scope.lastLink = response.data.links.last;
                $scope.nextLink = response.data.links.next;
                $scope.prevLink = response.data.links.prev;

                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   

            }, function myError(response) {
                $scope.myMessage = "Error!";
                $scope.response = response;
                $scope.statuscode = response.status;
                $scope.statustext = response.statusText;
                $scope.statusheaders = response.headers(); 
                $scope.statusconfig = response.config;   
            });
        }
        $(window).scroll(function() {
            if ($(window).scrollTop() + $(window).height() == $(document).height()) {
                $scope.getNext();
            }
        });
    });

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
95
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я знаю, что вы спрашивали, как это сделать с помощью angular, но ng-mouseenter и ng-mouseleave ОЧЕНЬ требовательны к производительности, если вы планируете использовать это в реальном приложении, это действительно должно быть сделано с помощью css.

Я покажу вам, как исправить вашу версию, а затем дам вам версию css, которая НАМНОГО эффективнее :)

Для этого варианта использования есть очень полезная переменная $ index, на которую можно ссылаться в шаблоне angular в любом месте внутри тега ng-repeat, чтобы получить индекс текущего элемента данных, по которому выполняется итерация. Вы должны использовать это, чтобы сохранить индекс элемента, который в настоящее время зависает в области контроллера. Затем, когда мышь покинет элемент, вы можете отказаться от сохраненного индекса.

Затем, когда вы назначаете стили, вы можете использовать троицу для назначения активных или неактивных стилей в зависимости от того, соответствует ли индекс элементов активной переменной индекса, сохраненной в области видимости.

Кроме того, если вы не знакомы с, тернарное выражение является сокращением условного оператора в форме conditional_expression ? value_returned_if_true : value_returned_if_false. Это хорошо для написания очень сжатых условных операторов в javascript (или, в данном случае, в шаблоне angular с интерпретацией javascript :))

Итак, в этом примере я использую комбинацию тернарного выражения и сохраняю индекс последнего элемента, введенного мышью, чтобы назначить стили при наведении или отсутствии зависания для каждого элемента.

И сокращенная версия вашего примера:

Угловой контроллер:

app.controller('exampleController', function($scope) {
  $scope.overlayColorStyles = {"opacity": 0};
  $scope.overlayTextStyles  = {"opacity": 0};
  $scope.overlayTextStylesActive  = {"opacity": 1};
  $scope.overlayColorStylesActive = { "opacity": .75};
  $scope.activeItemIndex    = null;
});

Шаблон:

<div id = "outer" class = "outer">
  <div class = "inner"
      ng-mouseenter = "$scope.activeItemIndex = $index"
      ng-mouseleave = "$scope.activeItemIndex = null"
      ng-repeat = "x in insideData">
      <img ng-if = "x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
      <div ng-if = "x.service=='Twitter'&& x.mediaType!='image'" class = "outer-caption"><div class = "inner-caption">{{x.caption}}</div></div>
      <div class = "overlay-color"
        ng-style = "$scope.activeItemIndex === $index ? overlayColorStylesActive : overlayColorStyles">
      </div>
      <div class = "overlay-text"
        ng-style = "$scope.activeItemIndex === $index ? overlayTextStylesActive : overlayTextStyles">
        VIEW
      </div>
  </div>
</div>

Опять же, этот код следует использовать только в учебных целях. Задача Angular - не применять стили на основе взаимодействия с пользователем, и если вы попытаетесь использовать его таким образом, ваше приложение станет очень медленным, когда вы начнете добавлять больше элементов. Сделать это с помощью css довольно тривиально и значительно повысит производительность :)

css версия ниже:

html:

<div id = "outer" class = "outer">
  <div class = "inner"
      ng-repeat = "x in insideData">
      <img ng-if = "x.service=='Instagram'||(x.service=='Twitter' && x.mediaType=='image')" ng-src='{{x.thumbnails[0].url}}'>
      <div ng-if = "x.service=='Twitter'&& x.mediaType!='image'" class = "outer-caption"><div class = "inner-caption">{{x.caption}}</div></div>
      <div class = "overlay-color"></div>
      <div class = "overlay-text">VIEW</div>
  </div>
</div>

css

.overlay-color {
  opacity: 0.0;
}

.overlay-text {
  opacity: 0.0;
}

.inner:hover .overlay-text {
  opacity: 1.0;
}

.inner:hover .overlay-color {
  opacity: 0.75;
}

Спасибо за этот ответ. Это исправило проблему идеально. Забавно то, что я изначально пытался построить его не угловым способом, но наведение не работало, потому что оно было у меня в классах .overlay-text и .overlay-color, а не в классе .inner. Еще раз спасибо. Аарону за идеальный ответ на мою проблему. Если вы не преподаете информатику, чтобы заработать себе на жизнь, вы должны это сделать, потому что, возможно, вы упускаете свое призвание.

Peter Mingione 05.05.2018 20:24

Ха-ха. Спасибо! Но боюсь, что у меня не будет никаких шансов сделать что-нибудь крутое, если я возьму на себя преподавательскую должность. :) Но если бы вы могли отметить мой ответ как правильный, моя оценка репутации переполнения стека определенно была бы признательна! ;)

Aaron Pool 05.05.2018 20:27

Другие вопросы по теме