Я новичок в 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();
}
});
});



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я знаю, что вы спрашивали, как это сделать с помощью 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. Еще раз спасибо. Аарону за идеальный ответ на мою проблему. Если вы не преподаете информатику, чтобы заработать себе на жизнь, вы должны это сделать, потому что, возможно, вы упускаете свое призвание.