у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет. Вопрос знатокам, что не так? |
Анимация и интерактивность Drawing API
Превращения фрукта
В этом упражнении мы создадим промежуточные сцены для движения и цвета между двумя рисунками API. Откройте apples_oranges.swf (на компакт-диске) и щелкните на фрукте. Он будет превращаться из яблока в апельсин при каждом щелчке пользователя. Не впечатляет? Но, между прочим, этот объект был создан полностью с помощью рисования API, без рисунков на рабочем столе или в Library!
Для начала создадим законченные рисунки.
- Создайте новый фильм с именем apple_oranges.fla. В этом фильме мы будем работать только с кодом, поэтому понадобится только панель Actions. Начните с добавления следующего кода в первый кадр слоя по умолчанию.
this.createEmptyMovieClip("drawObj", 0); apple = {}; apple.anchorPoints = [[245,155], [180,50], [245,155], [247,70], [265,60], [262,150], К[335,130], [354,220], [256,320], [163,263], [161,158], [262,150]]; apple.controlPoints = [[250,50], [150,100], [270,115], [255,70], [290,110], [290,109], К[373,153], [314,358], [211,357], [128,196], [200,118]]; apple.colors = [[0,0x009900], [2,0x663300], [5,0x990000]]; orange = {}; orange.anchorPoints = [[232,152], [192,120], [227,153], [307,103], [227,154], К[210,154], [260,148], [350,150], [380,338], [140,364], [133,175], [210,154]]; orange.controlPoints = [[212,58], [130,123], [246,102], [276,154], [200,104], К[230,124], [285,125], [450,204], [288,480], [38,263], [178,140]]; orange.colors = [[0,0x333300], [2,0x335500], [5,0xFF9933]]; shapes = [apple, orange]; shapeNum = 0;
Пример 9.1.В первой строке мы создаем фильм, который будет содержать наши рисунки. Затем создаются два новых объекта, названные "apple" и "orange", т.е. яблоко и апельсин. Оба они имеют точки контроля, фиксированные точки и присвоенные цвета (все числа были сгенерированы другим SWF). Для цветов мы сохраняем цвета и позиции индексов фиксированных точек, на которых начинается цвет. Затем мы располагаем эти два объекта в массиве с именем shapes и устанавливаем текущую позицию индекса на 0 для яблока с помощью shapeNum.
Теперь мы создаем функцию, носящую соответствующее название drawShape и рисующую фигуры.
drawShape = function (shape) { drawObj.clear(); drawObj.lineStyle(2, 0, 100); currentColor = 0; drawObj.moveTo(shape.anchorPoints[0] [0], s hape.anchorPoints[0] [1]; for (var i = 0; i<shape.anchorPoints.length-1; i++) { if (shape.colors[currentColor] [0] == i) { drawObj.endFill() ; drawObj.beginFill(shape.colors[currentColor] [1] , 100); drawObj.moveTo(shape.anchorPoints[i] [0], shape, anchor Points [i] [1] ) ; currentColor++; } drawObj.curveTo(shape.controlPoints [i] [0], shape.controlPoints [i] [1], Кshape.anchorPoints [i+1] [0], shape.anchorPoints [i+1] [1]); } };
Большая часть этого кода совершенно ясна, если вы разбираетесь в массивах, поэтому разберемся досконально, как работают ссылки. Переменная shape будет содержать ссылку на один из наших объектов - яблоко или апельсин. Следовательно, shape.anchorPoints будет ссылаться на параметр anchorPoints выделенной фигуры. anchorPoints для каждого объекта содержит двумерный массив. Каждая позиция индекса anchorPoints содержит координаты _x и _y: значение _x содержится в индексе 0, а значение _y содержится в индексе 1. Следовательно, если shape содержит наш объект apple, то shape.anchorPoints[1] [1] будет ссылаться на координату _y второго индекса массива anchorPoints объекта apple, которым является 50.
В функции drawShape мы сначала удаляем фильм, сбрасываем переменные lineStyle и currentColor и переходим на нашу начальную позицию. Мы проходим через весь массив anchorPoints для нашего текущего объекта и вызываем метод curveTo для каждого из них. Выражение if проверяет, находимся ли мы на позиции индекса, где должен начаться наш следующий цвет. Если это так, мы заканчиваем предыдущую заливку и начинаем новую. Я выяснил, что перемещение "карандаша" на текущую позицию после вызова beginFill устранило некоторые ошибки заполнения, имевшиеся при отсутствии этой команды.
- Теперь введите последний фрагмент кода.
clickCatch = function () { shapeNum = shapeNum+1>1 ? 0 : shapeNum+1; drawShape(shapes[shapeNum]); }; drawShape(apple); drawObj.onMouseDown = clickCatch;
При щелчке мышью будет вызываться функция clickCatch. Она увеличивает shapeNum (мы используем здесь условный оператор на тот случай, если нам понадобится добавить дополнительные фигуры впоследствии) и вызывает нашу функцию drawShape. После этого рисуется начальная фигура, и drawObj настраивается на регистрацию щелчков мыши для изменения рисунка. Запустите фильм, чтобы отобразить яблоко, затем щелкните мышью, и появится апельсин. Все это реализовано с помощью вышеуказанного кода.
Мы нарисовали фрукты с помощью рисования API. Хорошо было бы анимировать это изменение. Попробуем реализовать такую возможность.
- Добавьте эти три строки в верхнюю часть вашего текущего кода, сразу после вызова createEmptyMovieClip.
tweenRate = 24; currentPos = {}; currentPos.controlPoints = []; currentPos.anchorPoints = []; currentPos.colors = [];
Здесь мы просто инициализируем переменные. tweenRate является длиной нашей анимации, связанной с частотой кадров. currentPos будет содержать всю информацию о том, на какую сцену в данный момент указывают наши фиксированные точки, точки контроля и цвета.
- Еще одна функция представлена на ваше утверждение. Введите этот код сразу под функцией drawShape.
convertToRGB = function(c) { var col = c.toString(16); while (col.length < 6) { col = "0" + col; } var r = parseInt(col.substr(0,2), 16); var g = parseInt(col.substr(2,2), 16); var b = parseInt(col.substr(4,2), 16); return {r:r, g:g, b:b} }
Функция convertToRGB выполняет преобразование в цветовую систему RGB. Она будет получать значение цвета и возвращать значение для каждого из трех цветов - красного, зеленого и синего. Эти значения понадобятся нам для плавного изменения цветов объектов.
c - это значение цвета, получаемое функцией. Мы преобразовываем его в строку с помощью метода toString, с использованием шестнадцатеричной системы. Выражение while нужно для проверки того, что в строке содержится шесть символов. Например, если мы отправляем функции значение 255 (чистый синий), строкой, возвращенной c.toString(16) будет FF. Нам необходимо, чтобы строка имела вид 0000FF для шестнадцатеричного представления цвета, поэтому в выражении while мы добавляем необходимые нули.
Далее, мы извлекаем три подстроки из c. r будет содержать значение красного цвета, хранимое в первых двух символах строки, g будет содержать значение зеленого цвета в третьем и четвертом символах строки, а b будет содержать последние два символа, представляющие собой значение для синего цвета. parseInt преобразует строку в число, поэтому мы отправляем функции наши подстроки, а также основание системы исчисления (16). Эти конечные значения возвращаются в отдельном объекте, содержащем три параметра: r, g и b.
- Следующая функция является местом инициализации преобразования. Введите этот код сразу после функции convertToRGB.
startShift = function (shape) { endShape = shape; delete drawObj.onMouseDown; tweenCount = 0; increment = {}; increment.anchorPoints = []; increment.controlPoints = []; increment. colors = []; for (var i = 0; i<shape.colors.length; i++) { var newColor = convertToRGB(shape.colors[i] [1] ); var oldColor = convertToRGB(currentPos.colors[i] [1] ) ; var r = (oldColor.r - newColor.r)/tweenRate; var g = (oldColor.g - newColor.g)/tweenRate; var b = (oldColor.b - newColor.b)/tweenRate; increment.colors.push({r:r, g: g, b:b}); } for (var i = 0; i < shape.anchorPoints.length; i++) { var anchor1 = (shape.anchorPoints[i] [0] - КcurrentPos.anchorPoints [i] [0])/tweenRate; var anchor2 = (shape.anchorPoints[i] [1] - КcurrentPos .anchorPoints [i] [1])/tweenRate; var controll = (shape.controlPoints[i] [0] - КcurrentPos.controlPoints[i] [0])/tweenRate; var control2 = (shape.controlPoints[i] [1] - КcurrentPos.controlPoints [i] [1])/tweenRate; increment.anchorPoints.push([anchor1, anchor2]); increment.controlPoints.push([control1, control2]); } drawObj.onEnterFrame = moveLines; };
Пример 9.2.Подготовительные действия завершены. Собственно вся подготовка и заключается в этой функции. startShift отсылается при любой конечной фигуре, а это значение хранится в endShape. После этого удаляется mouseDown, чтобы пользователь не мог щелкать мышью во время трансформации (не беспокойтесь, позднее мы вернем все на свои места).
Далее: increment необходим для хранения значений, которые понадобятся нам для настройки текущей фигуры в каждом кадре. Мы проходим через все цвета, точки контроля и фиксированные точки currentPos (сейчас мы опишем currentPos ), находим разность между этими значениями и конечными значениями, затем делим эту разность на tweenRate. Это даст нам значение increment, нужное для настройки currentPos в каждом кадре для преобразования одной фигуры в другую. Эти значения помещаются в соответствующие массивы объекта increment.
Наконец, нужно настроить наш объект на вызов в каждом кадре функции moveLines. Разумеется, нам понадобится написать эту функцию.
- Введите этот код сразу после предыдущей функции.
moveLines = function () { for (var i = 0; i<endShape.anchorPoints.length; i++) { currentPos.controlPoints[i] [0] += increment.controlPoints [i] [0]; currentPos.controlPoints[i] [1] += increment.controlPoints [i] [1] ; currentPos.anchorPoints[i] [0] += increment.anchorPoints[i] [0]; currentPos.anchorPoints[i] [1] += increment.anchorPoints[i] [1]; } for (var i = 0; i < endShape.colors.length; i++) { var col = convertToRGB(currentPos.colors[i] [1]); col.r = Math.round(col.r-increment.colors[i] .r); col.g = Math.round(col.g-increment.colors[i] .g); col.b = Math.round(col.b-increment.colors[i] .b); currentPos.colors [i] [1] = col.r << 16 | col.g << 8 | col.b; } drawShape(currentPos); tweenCount++; if (tweenCount>tweenRate) { delete drawObj.onEnterFrame; drawobj.onMouseDown = clickCatch; drawShape(endShape); } };
Эта функция непосредственно обеспечивает трансформацию, хотя она и не настолько сложна, чтобы обсуждать ее. Она просто настраивает числа в currentPos в каждом кадре c использованием соответствующих значений increment. После этого она вызывает drawShape (функция рисования, написанная нами в самом начале кода) и проверяет, является ли данный кадр последним кадром трансформации. Если это так, она сбрасывает все значения, останавливает анимацию и подготавливается к следующему щелчку мыши.
- Мы почти закончили. Настроим нашу функцию drawShape для работы с новым объектом currentPos. Обновите функцию drawShape следующими новыми строками (выделены жирным шрифтом).
drawShape = function (shape) { drawObj.clear(); drawObj.lineStyle(2, 0, 100); currentColor = 0; drawObj.moveTo(shape.anchorPoints[0] [0] , shape.anchorPoints [0] [1]); for (var i = 0; i<shape.anchorPoints.length-1; i++) { if (shape.colors[currentColor] [0] == i) { drawObj.endFill(); drawObj.beginFill(shape.colors[currentColor] [1], 100); currentPos.colors[currentColor] = К[i, shape.colors[currentColor][1]]; drawObj.moveTo(shape.anchorPoints[i] [0], shape.anchorPoints[i] [1] ) ; currentColor++; } drawObj.curveTo(shape.controlPoints[i] [0], Кshape.controlPoints [i] [1], shape.anchorPoints [i+1] [0], Кshape.anchorPoints[i+1] [1]); currentPos.controlPoints[i] = [shape.controlPoints[i] [0], Кshape.controlPoints[i] [1]]; currentPos.anchorPoints[i] = [shape.anchorPoints[i][0], Кshape.anchorPoints [i] [1]]; } currentPos.anchorPoints[i] = [shape.anchorPoints[i][0], Кshape.anchorPoints[i][1]]; };
Эти дополнительные строки сохраняют номера текущих позиций точек, чтобы можно было использовать их в следующем кадре нашей функции moveLines. Проследите за превращением и вы увидите, как эти значения влияют на фильм.
- Наконец, измените функцию clickCatch так, чтобы при щелчке пользователем начиналась трансформация. Это реализуется вызовом функции startShift.
clickCatch = function () { shapeNum = shapeNum+1>1 ? 0 : shapeNum+1; startShift(shapes[shapeNum]); };
- Теперь запустите фильм, чтобы увидеть превращение одного фрукта в другой. Здорово!